commit 46fae36cd010322fcd05ac4634c928f15fb8d3a3 Author: Victor Nguyen Date: Tue Feb 19 18:02:59 2013 +1100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d54cf4f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +#Mac OS X files +.DS_Store \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..b260819 --- /dev/null +++ b/app.js @@ -0,0 +1,36 @@ + +/** + * Module dependencies. + */ + +var express = require('express'), + _ = require('underscore'), + routes = require('./routes'), + specs = require('./routes/specs'), + http = require('http'), + path = require('path'); + +var app = express(); + +app.configure(function(){ + app.set('port', process.env.PORT || 3000); + app.set('views', __dirname + '/views'); + app.set('view engine', 'jade'); + app.use(express.favicon()); + app.use(express.logger('dev')); + app.use(express.bodyParser()); + app.use(express.methodOverride()); + app.use(app.router); + app.use(express.static(__dirname, 'public')); +}); + +app.configure('development', function(){ + app.use(express.errorHandler()); +}); + +app.get('/', routes.index); +app.get('/specs/:model', specs.fetch); + +app.listen(app.get('port'), function(){ + console.log("Express server listening on port " + app.get('port')); +}); diff --git a/example.html b/example.html new file mode 100644 index 0000000..72fc2e6 --- /dev/null +++ b/example.html @@ -0,0 +1,1702 @@ + + +
+
+ +
+ + + + + + + +
 ClassicLuxury
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Engine type3.7 litre V6 24 valve DOHC S-VT3.7 litre V6 24 valve DOHC S-VT
Engine capacity3,726 cc3,726 cc
Bore and stroke95.5 mm x 86.7 mm95.5 mm x 86.7 mm
Compression ratio10.3 : 110.3 : 1
Maximum power204 kW @ 6,250 rpm204 kW @ 6,250 rpm
Maximum torque367 Nm @ 4,250 rpm367 Nm @ 4,250 rpm
Throttle controlElectronic (drive-by-wire)Electronic (drive-by-wire)
Fuel systemElectronic port injectionElectronic port injection
Fuel tank capacity76 litres76 litres
Recommended fuelUnleaded (91RON or higher) or E10Unleaded (91RON or higher) or E10
Fuel consumption (combined)111.0 (FWD) 11.2 (AWD) litres per 100 km11.0 (FWD) 11.2 (AWD) litres per 100 km
Emissions standardEuro stage VEuro stage V
Activematic (auto) transmission6-speed6-speed
Gear ratio 1st4.1484.148
Gear ratio 2nd2.3702.370
Gear ratio 3rd1.5551.555
Gear ratio 4th1.1541.154
Gear ratio 5th0.8590.859
Gear ratio 6th0.6850.685
Gear ratio reverse3.3933.393
Gear ratio final drive3.4643.464
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
All-Wheel Drive (AWD) system--
Brake diameter front320 mm320 mm
Brake diameter rear325 mm325 mm
Brake type frontVentilated discVentilated disc
Brake type rearVentilated discVentilated disc
Steering typeHydraulic power assist steeringHydraulic power assist steering
Suspension frontMacPherson strutMacPherson strut
Suspension rearMulti-linkMulti-link
Turning circle kerb to kerb11.4 m11.4 m
Tyre size245/60 R18245/50 R20
Tyre index104H102V
Wheel size18 x 7.5 J20 x 7.5 J
Wheel typeAlloyAlloy
Tyre size (spare)195/80 R17195/80 R17
Wheel type (spare)SteelSteel
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Aerial printed into rear glassTickTick
Daytime running lamps (LED)--
Door handles (chrome)-Tick
Exhaust extensions (chrome)TickTick
Fog-lamps (front)TickTick
Front and rear bumpers (body coloured)TickTick
Green-tinted windscreen, side and rear windowsTickTick
Headlamps (Bi-Xenon)--
Headlamps (Halogen)TickTick
Metallic/Mica paintNo cost optionNo cost option
Mudflaps (front and rear)TickTick
Power mirrors (body coloured)TickTick
Power mirrors (heated with 3-position memory and reverse tilt-down function)-Tick
Power-sliding and tilt glass sunroof-Tick
Power windowsTickTick
Rear spoilerTickTick
Remote operated power tailgate (open/close)--
Roof rack mounting pointsTickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Advanced keyless entry and engine start--
Air-conditioning (three-zone climate control with independent rear control)TickTick
Ambient temperature displayTickTick
Bluetooth® (hands-free compatible)2TickTick
Cargo area 12 volt power outletTickTick
Cargo area tie-down hooksTickTick
Cargo area underfloor storage boxTickTick
Centre armrest consoleTickTick
Critical function warning lights/chimesTickTick
Cruise controlTickTick
CupholdersTickTick
Digital clockTickTick
Door map pockets (front)TickTick
Driver’s left footrestTickTick
Glasses storage compartmentTickTick
Glove box (illuminated)TickTick
Headlamps auto on/off functionTickTick
Heating ducts to second and third row passengersTickTick
Illuminated entry system with delayed fadeTickTick
Instrument panel light dimmerTickTick
Interior illumination: cargo room lampTickTick
Interior illumination: map reading spot lampsTickTick
Interior illumination: power window switchesTickTick
Interior release for fuel filler doorTickTick
Leather-wrapped: gear shift knobTickTick
Leather-wrapped: steering wheelTickTick
Passenger assist grips (front and rear)TickTick
Satellite navigation (TomTom)-Tick
Seat trim: clothTick-
Seat trim: leather3-Tick
Seats (front) with: 3-position memory function (driver)-Tick
Seats (front) with: 4-way power adjustment (passenger)-Tick
Seats (front) with: 8-way power adjustment (driver)-Tick
Seats (front) with: adjustable head restraintsTickTick
Seats (front) with: heating function-Tick
Seats (front) with: height adjustment (driver)TickTick
Seats (front) with: lumbar adjustment (driver)TickTick
Seats (front) with: rake and slide adjustmentTickTick
Seats (front) with: seat back pocketsTickTick
Seats (front) with: seat-base tilt adjustment (driver)-Tick
Seats (2nd row) with: 60/40 split-fold backrestTickTick
Seats (2nd row) with: adjustable head restraintsTickTick
Seats (2nd row) with: centre fold down armrestTickTick
Seats (2nd row) with: rake and slide adjustmentTickTick
Seats (3rd row) with: 50/50 split-fold backrest (flat fold)TickTick
Seats (3rd row) with: adjustable head restraintsTickTick
Tachometer and electronic odometer/tripmeterTickTick
Tilt and telescopic adjustable steering wheelTickTick
Trip computer (current and average fuel consumption, distance to empty and average vehicle speed)TickTick
Vanity mirrors (front) with illuminationTickTick
Ventilation pollen filterTickTick
Window demister (rear)TickTick
Wipers (front) 2-speed with rain-sensing functionTickTick
Wiper (rear) with intermittent functionTickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AM/FM tunerTickTick
Auxiliary input (3.5 mm MP3 player compatible)TickTick
Bluetooth® audio (MP3 player compatible)2TickTick
CD player, single disc (MP3/WMA compatible)TickTick
Premium Bose® 277 watt amplifier and speakers (including subwoofer)-Tick
Speakers (6)Tick-
Speakers (10)-Tick
Steering wheel-mounted audio controlsTickTick
USB input (iPod® compatible)TickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Airbags SRS: front (driver and passenger), side (front), curtain (front and rear)TickTick
Anti-lock Braking System (ABS)TickTick
Blind Spot Monitoring (BSM)--
Child restraint anchor points (2nd row only)TickTick
Childproof rear door locksTickTick
‘Dual stage’ door unlocking functionTickTick
Dynamic Stability Control (DSC)TickTick
Electronic Brake-force Distribution (EBD)TickTick
Emergency Brake Assist (EBA)TickTick
Emergency Stop Signal (ESS)TickTick
Engine immobiliserTickTick
Forward Obstruction Warning (FOW)--
High Beam Control (HBC)--
High mount stop lampTickTick
Lane Departure Warning (LDW)--
Left-hand-side convex (wide angle) exterior mirrorTickTick
One touch (up and down) power window (driver and passenger)TickTick
Parking sensors (rear)--
Rear-view mirror with auto dimming function--
Remote central locking (2 transmitters)TickTick
Reverse cameraTickTick
Roll Stability Control (RSC)TickTick
Seat-belts 3-point lap-sash (all seats)TickTick
Seat-belts (front) with pretensioners, load-limiters and height adjustable shoulder anchoragesTickTick
Side impact door beamsTickTick
Traction Control System (TCS)TickTick
‘Triple H’ safety construction with front and rear crumple zonesTickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Ground clearance laden147 mm147 mm
Overall length5,106 mm5,106 mm
Overall width1,936 mm1,936 mm
Overall height1,728 mm1,728 mm
Track front1,654 mm1,654 mm
Track rear1,644 mm1,644 mm
Wheelbase2,875 mm2,875 mm
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Seating capacity77
Cargo room volume (VDA)4267 litres267 litres
Cargo room volume (VDA)5928 litres928 litres
Kerb weight1,939 kg1,966 kg
Tow-ball download maximum150 kg150 kg
Towing capacity6 braked2,000 kg2,000 kg
Towing capacity6 unbraked750 kg750 kg
+
+
+ +
+ + + + + + + +
 LuxuryGrand Touring
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Engine type3.7 litre V6 24 valve DOHC S-VT3.7 litre V6 24 valve DOHC S-VT
Engine capacity3,726 cc3,726 cc
Bore and stroke95.5 mm x 86.7 mm95.5 mm x 86.7 mm
Compression ratio10.3 : 110.3 : 1
Maximum power204 kW @ 6,250 rpm204 kW @ 6,250 rpm
Maximum torque367 Nm @ 4,250 rpm367 Nm @ 4,250 rpm
Throttle controlElectronic (drive-by-wire)Electronic (drive-by-wire)
Fuel systemElectronic port injectionElectronic port injection
Fuel tank capacity76 litres76 litres
Recommended fuelUnleaded (91RON or higher) or E10Unleaded (91RON or higher) or E10
Fuel consumption (combined)111.0 (FWD) 11.2 (AWD) litres per 100 km11.0 (FWD) 11.2 (AWD) litres per 100 km
Emissions standardEuro stage VEuro stage V
Activematic (auto) transmission6-speed6-speed
Gear ratio 1st4.1484.148
Gear ratio 2nd2.3702.370
Gear ratio 3rd1.5551.555
Gear ratio 4th1.1541.154
Gear ratio 5th0.8590.859
Gear ratio 6th0.6850.685
Gear ratio reverse3.3933.393
Gear ratio final drive3.4643.464
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
All-Wheel Drive (AWD) systemActive Torque Split (ATS)Active Torque Split (ATS)
Brake diameter front320 mm320 mm
Brake diameter rear325 mm325 mm
Brake type frontVentilated discVentilated disc
Brake type rearVentilated discVentilated disc
Steering typeHydraulic power assist steeringHydraulic power assist steering
Suspension frontMacPherson strutMacPherson strut
Suspension rearMulti-linkMulti-link
Turning circle kerb to kerb11.4 m11.4 m
Tyre size245/50 R20245/50 R20
Tyre index102V102V
Wheel size20 x 7.5 J20 x 7.5 J
Wheel typeAlloyAlloy
Tyre size (spare)195/80 R17195/80 R17
Wheel type (spare)SteelSteel
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Aerial printed into rear glassTickTick
Daytime running lamps (LED)-Tick
Door handles (chrome)TickTick
Exhaust extensions (chrome)TickTick
Fog-lamps (front)TickTick
Front and rear bumpers (body coloured)TickTick
Green-tinted windscreen, side and rear windowsTickTick
Headlamps (Bi-Xenon)-Tick
Headlamps (Halogen)Tick-
Metallic/Mica paintNo cost optionNo cost option
Mudflaps (front and rear)TickTick
Power mirrors (body coloured)TickTick
Power mirrors (heated with 3-position memory and reverse tilt-down function)TickTick
Power-sliding and tilt glass sunroofTickTick
Power windowsTickTick
Rear spoilerTickTick
Remote operated power tailgate (open/close)-Tick
Roof rack mounting pointsTickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Advanced keyless entry and engine start-Tick
Air-conditioning (three-zone climate control with independent rear control)TickTick
Ambient temperature displayTickTick
Bluetooth® (hands-free compatible)2TickTick
Cargo area 12 volt power outletTickTick
Cargo area tie-down hooksTickTick
Cargo area underfloor storage boxTickTick
Centre armrest consoleTickTick
Critical function warning lights/chimesTickTick
Cruise controlTickTick
CupholdersTickTick
Digital clockTickTick
Door map pockets (front)TickTick
Driver’s left footrestTickTick
Glasses storage compartmentTickTick
Glove box (illuminated)TickTick
Headlamps auto on/off functionTickTick
Heating ducts to second and third row passengersTickTick
Illuminated entry system with delayed fadeTickTick
Instrument panel light dimmerTickTick
Interior illumination: cargo room lampTickTick
Interior illumination: map reading spot lampsTickTick
Interior illumination: power window switchesTickTick
Interior release for fuel filler doorTickTick
Leather-wrapped: gear shift knobTickTick
Leather-wrapped: steering wheelTickTick
Passenger assist grips (front and rear)TickTick
Satellite navigation (TomTom)TickTick
Seat trim: cloth--
Seat trim: leather3TickTick
Seats (front) with: 3-position memory function (driver)TickTick
Seats (front) with: 4-way power adjustment (passenger)TickTick
Seats (front) with: 8-way power adjustment (driver)TickTick
Seats (front) with: adjustable head restraintsTickTick
Seats (front) with: heating functionTickTick
Seats (front) with: height adjustment (driver)TickTick
Seats (front) with: lumbar adjustment (driver)TickTick
Seats (front) with: rake and slide adjustmentTickTick
Seats (front) with: seat back pocketsTickTick
Seats (front) with: seat-base tilt adjustment (driver)TickTick
Seats (2nd row) with: 60/40 split-fold backrestTickTick
Seats (2nd row) with: adjustable head restraintsTickTick
Seats (2nd row) with: centre fold down armrestTickTick
Seats (2nd row) with: rake and slide adjustmentTickTick
Seats (3rd row) with: 50/50 split-fold backrest (flat fold)TickTick
Seats (3rd row) with: adjustable head restraintsTickTick
Tachometer and electronic odometer/tripmeterTickTick
Tilt and telescopic adjustable steering wheelTickTick
Trip computer (current and average fuel consumption, distance to empty and average vehicle speed)TickTick
Vanity mirrors (front) with illuminationTickTick
Ventilation pollen filterTickTick
Window demister (rear)TickTick
Wipers (front) 2-speed with rain-sensing functionTickTick
Wiper (rear) with intermittent functionTickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AM/FM tunerTickTick
Auxiliary input (3.5 mm MP3 player compatible)TickTick
Bluetooth® audio (MP3 player compatible)2TickTick
CD player, single disc (MP3/WMA compatible)TickTick
Premium Bose® 277 watt amplifier and speakers (including subwoofer)TickTick
Speakers (6)--
Speakers (10)TickTick
Steering wheel-mounted audio controlsTickTick
USB input (iPod® compatible)TickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Airbags SRS: front (driver and passenger), side (front), curtain (front and rear)TickTick
Anti-lock Braking System (ABS)TickTick
Blind Spot Monitoring (BSM)-Tick
Child restraint anchor points (2nd row only)TickTick
Childproof rear door locksTickTick
‘Dual stage’ door unlocking functionTickTick
Dynamic Stability Control (DSC)TickTick
Electronic Brake-force Distribution (EBD)TickTick
Emergency Brake Assist (EBA)TickTick
Emergency Stop Signal (ESS)TickTick
Engine immobiliserTickTick
Forward Obstruction Warning (FOW)-Tick
High Beam Control (HBC)-Tick
High mount stop lampTickTick
Lane Departure Warning (LDW)-Tick
Left-hand-side convex (wide angle) exterior mirrorTickTick
One touch (up and down) power window (driver and passenger)TickTick
Parking sensors (rear)-Tick
Rear-view mirror with auto dimming function-Tick
Remote central locking (2 transmitters)TickTick
Reverse cameraTickTick
Roll Stability Control (RSC)TickTick
Seat-belts 3-point lap-sash (all seats)TickTick
Seat-belts (front) with pretensioners, load-limiters and height adjustable shoulder anchoragesTickTick
Side impact door beamsTickTick
Traction Control System (TCS)TickTick
‘Triple H’ safety construction with front and rear crumple zonesTickTick
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Ground clearance laden147 mm147 mm
Overall length5,106 mm5,106 mm
Overall width1,936 mm1,936 mm
Overall height1,728 mm1,728 mm
Track front1,654 mm1,654 mm
Track rear1,644 mm1,644 mm
Wheelbase2,875 mm2,875 mm
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Seating capacity77
Cargo room volume (VDA)4267 litres267 litres
Cargo room volume (VDA)5928 litres928 litres
Kerb weight2,070 kg2,086 kg
Tow-ball download maximum150 kg150 kg
Towing capacity6 braked2,000 kg2,000 kg
Towing capacity6 unbraked750 kg750 kg
+
+
+ +
+
diff --git a/node_modules/.bin/express b/node_modules/.bin/express new file mode 100755 index 0000000..3c0090c --- /dev/null +++ b/node_modules/.bin/express @@ -0,0 +1,422 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var exec = require('child_process').exec + , program = require('commander') + , mkdirp = require('mkdirp') + , pkg = require('../package.json') + , version = pkg.version + , os = require('os') + , fs = require('fs'); + +// CLI + +program + .version(version) + .option('-s, --sessions', 'add session support') + .option('-e, --ejs', 'add ejs engine support (defaults to jade)') + .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)') + .option('-H, --hogan', 'add hogan.js engine support') + .option('-c, --css ', 'add stylesheet support (less|stylus) (defaults to plain css)') + .option('-f, --force', 'force on non-empty directory') + .parse(process.argv); + +// Path + +var path = program.args.shift() || '.'; + +// end-of-line code + +var eol = 'win32' == os.platform() ? '\r\n' : '\n' + +// Template engine + +program.template = 'jade'; +if (program.ejs) program.template = 'ejs'; +if (program.jshtml) program.template = 'jshtml'; +if (program.hogan) program.template = 'hjs'; + +/** + * Routes index template. + */ + +var index = [ + '' + , '/*' + , ' * GET home page.' + , ' */' + , '' + , 'exports.index = function(req, res){' + , ' res.render(\'index\', { title: \'Express\' });' + , '};' +].join(eol); + +/** + * Routes users template. + */ + +var users = [ + '' + , '/*' + , ' * GET users listing.' + , ' */' + , '' + , 'exports.list = function(req, res){' + , ' res.send("respond with a resource");' + , '};' +].join(eol); + +/** + * Jade layout template. + */ + +var jadeLayout = [ + 'doctype 5' + , 'html' + , ' head' + , ' title= title' + , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')' + , ' body' + , ' block content' +].join(eol); + +/** + * Jade index template. + */ + +var jadeIndex = [ + 'extends layout' + , '' + , 'block content' + , ' h1= title' + , ' p Welcome to #{title}' +].join(eol); + +/** + * EJS index template. + */ + +var ejsIndex = [ + '' + , '' + , ' ' + , ' <%= title %>' + , ' ' + , ' ' + , ' ' + , '

<%= title %>

' + , '

Welcome to <%= title %>

' + , ' ' + , '' +].join(eol); + +/** + * JSHTML layout template. + */ + +var jshtmlLayout = [ + '' + , '' + , ' ' + , ' @write(title) ' + , ' ' + , ' ' + , ' ' + , ' @write(body)' + , ' ' + , '' +].join(eol); + +/** + * JSHTML index template. + */ + +var jshtmlIndex = [ + '

@write(title)

' + , '

Welcome to @write(title)

' +].join(eol); + +/** + * Hogan.js index template. + */ +var hoganIndex = [ + '' + , '' + , ' ' + , ' {{ title }}' + , ' ' + , ' ' + , ' ' + , '

{{ title }}

' + , '

Welcome to {{ title }}

' + , ' ' + , '' +].join(eol); + +/** + * Default css template. + */ + +var css = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default less template. + */ + +var less = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default stylus template. + */ + +var stylus = [ + 'body' + , ' padding: 50px' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif' + , 'a' + , ' color: #00B7FF' +].join(eol); + +/** + * App template. + */ + +var app = [ + '' + , '/**' + , ' * Module dependencies.' + , ' */' + , '' + , 'var express = require(\'express\')' + , ' , routes = require(\'./routes\')' + , ' , user = require(\'./routes/user\')' + , ' , http = require(\'http\')' + , ' , path = require(\'path\');' + , '' + , 'var app = express();' + , '' + , 'app.configure(function(){' + , ' app.set(\'port\', process.env.PORT || 3000);' + , ' app.set(\'views\', __dirname + \'/views\');' + , ' app.set(\'view engine\', \':TEMPLATE\');' + , ' app.use(express.favicon());' + , ' app.use(express.logger(\'dev\'));' + , ' app.use(express.bodyParser());' + , ' app.use(express.methodOverride());{sess}' + , ' app.use(app.router);{css}' + , ' app.use(express.static(path.join(__dirname, \'public\')));' + , '});' + , '' + , 'app.configure(\'development\', function(){' + , ' app.use(express.errorHandler());' + , '});' + , '' + , 'app.get(\'/\', routes.index);' + , 'app.get(\'/users\', user.list);' + , '' + , 'http.createServer(app).listen(app.get(\'port\'), function(){' + , ' console.log("Express server listening on port " + app.get(\'port\'));' + , '});' + , '' +].join(eol); + +// Generate application + +(function createApplication(path) { + emptyDirectory(path, function(empty){ + if (empty || program.force) { + createApplicationAt(path); + } else { + program.confirm('destination is not empty, continue? ', function(ok){ + if (ok) { + process.stdin.destroy(); + createApplicationAt(path); + } else { + abort('aborting'); + } + }); + } + }); +})(path); + +/** + * Create application at the given directory `path`. + * + * @param {String} path + */ + +function createApplicationAt(path) { + console.log(); + process.on('exit', function(){ + console.log(); + console.log(' install dependencies:'); + console.log(' $ cd %s && npm install', path); + console.log(); + console.log(' run the app:'); + console.log(' $ node app'); + console.log(); + }); + + mkdir(path, function(){ + mkdir(path + '/public'); + mkdir(path + '/public/javascripts'); + mkdir(path + '/public/images'); + mkdir(path + '/public/stylesheets', function(){ + switch (program.css) { + case 'less': + write(path + '/public/stylesheets/style.less', less); + break; + case 'stylus': + write(path + '/public/stylesheets/style.styl', stylus); + break; + default: + write(path + '/public/stylesheets/style.css', css); + } + }); + + mkdir(path + '/routes', function(){ + write(path + '/routes/index.js', index); + write(path + '/routes/user.js', users); + }); + + mkdir(path + '/views', function(){ + switch (program.template) { + case 'ejs': + write(path + '/views/index.ejs', ejsIndex); + break; + case 'jade': + write(path + '/views/layout.jade', jadeLayout); + write(path + '/views/index.jade', jadeIndex); + break; + case 'jshtml': + write(path + '/views/layout.jshtml', jshtmlLayout); + write(path + '/views/index.jshtml', jshtmlIndex); + break; + case 'hjs': + write(path + '/views/index.hjs', hoganIndex); + break; + + } + }); + + // CSS Engine support + switch (program.css) { + case 'less': + app = app.replace('{css}', eol + ' app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));'); + break; + case 'stylus': + app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware(__dirname + \'/public\'));'); + break; + default: + app = app.replace('{css}', ''); + } + + // Session support + app = app.replace('{sess}', program.sessions + ? eol + ' app.use(express.cookieParser(\'your secret here\'));' + eol + ' app.use(express.session());' + : ''); + + // Template support + app = app.replace(':TEMPLATE', program.template); + + // package.json + var pkg = { + name: 'application-name' + , version: '0.0.1' + , private: true + , scripts: { start: 'node app' } + , dependencies: { + express: version + } + } + + if (program.template) pkg.dependencies[program.template] = '*'; + + // CSS Engine support + switch (program.css) { + case 'less': + pkg.dependencies['less-middleware'] = '*'; + break; + default: + if (program.css) { + pkg.dependencies[program.css] = '*'; + } + } + + write(path + '/package.json', JSON.stringify(pkg, null, 2)); + write(path + '/app.js', app); + }); +} + +/** + * Check if the given directory `path` is empty. + * + * @param {String} path + * @param {Function} fn + */ + +function emptyDirectory(path, fn) { + fs.readdir(path, function(err, files){ + if (err && 'ENOENT' != err.code) throw err; + fn(!files || !files.length); + }); +} + +/** + * echo str > path. + * + * @param {String} path + * @param {String} str + */ + +function write(path, str) { + fs.writeFile(path, str); + console.log(' \x1b[36mcreate\x1b[0m : ' + path); +} + +/** + * Mkdir -p. + * + * @param {String} path + * @param {Function} fn + */ + +function mkdir(path, fn) { + mkdirp(path, 0755, function(err){ + if (err) throw err; + console.log(' \033[36mcreate\033[0m : ' + path); + fn && fn(); + }); +} + +/** + * Exit with the given `str`. + * + * @param {String} str + */ + +function abort(str) { + console.error(str); + process.exit(1); +} diff --git a/node_modules/.bin/jade b/node_modules/.bin/jade new file mode 100755 index 0000000..8f1c816 --- /dev/null +++ b/node_modules/.bin/jade @@ -0,0 +1,168 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var fs = require('fs') + , program = require('commander') + , path = require('path') + , basename = path.basename + , dirname = path.dirname + , resolve = path.resolve + , exists = fs.existsSync || path.existsSync + , join = path.join + , mkdirp = require('mkdirp') + , jade = require('../'); + +// jade options + +var options = {}; + +// options + +program + .version(jade.version) + .usage('[options] [dir|file ...]') + .option('-o, --obj ', 'javascript options object') + .option('-O, --out ', 'output the compiled html to ') + .option('-p, --path ', 'filename used to resolve includes') + .option('-P, --pretty', 'compile pretty html output') + .option('-c, --client', 'compile function for client-side runtime.js') + .option('-D, --no-debug', 'compile without debugging (smaller functions)') + .option('-w, --watch', 'watch files for changes and automatically re-render') + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' # translate jade the templates dir'); + console.log(' $ jade templates'); + console.log(''); + console.log(' # create {foo,bar}.html'); + console.log(' $ jade {foo,bar}.jade'); + console.log(''); + console.log(' # jade over stdio'); + console.log(' $ jade < my.jade > my.html'); + console.log(''); + console.log(' # jade over stdio'); + console.log(' $ echo "h1 Jade!" | jade'); + console.log(''); + console.log(' # foo, bar dirs rendering to /tmp'); + console.log(' $ jade foo bar --out /tmp '); + console.log(''); +}); + +program.parse(process.argv); + +// options given, parse them + +if (program.obj) { + if (exists(program.obj)) { + options = JSON.parse(fs.readFileSync(program.obj)); + } else { + options = eval('(' + program.obj + ')'); + } +} + +// --filename + +if (program.path) options.filename = program.path; + +// --no-debug + +options.compileDebug = program.debug; + +// --client + +options.client = program.client; + +// --pretty + +options.pretty = program.pretty; + +// --watch + +options.watch = program.watch; + +// left-over args are file paths + +var files = program.args; + +// compile files + +if (files.length) { + console.log(); + files.forEach(renderFile); + if (options.watch) { + files.forEach(function (file) { + fs.watchFile(file, {interval: 100}, function (curr, prev) { + if (curr.mtime > prev.mtime) renderFile(file); + }); + }); + } + process.on('exit', function () { + console.log(); + }); +// stdio +} else { + stdin(); +} + +/** + * Compile from stdin. + */ + +function stdin() { + var buf = ''; + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(chunk){ buf += chunk; }); + process.stdin.on('end', function(){ + var fn = jade.compile(buf, options); + var output = options.client + ? fn.toString() + : fn(options); + process.stdout.write(output); + }).resume(); +} + +/** + * Process the given path, compiling the jade files found. + * Always walk the subdirectories. + */ + +function renderFile(path) { + var re = /\.jade$/; + fs.lstat(path, function(err, stat) { + if (err) throw err; + // Found jade file + if (stat.isFile() && re.test(path)) { + fs.readFile(path, 'utf8', function(err, str){ + if (err) throw err; + options.filename = path; + var fn = jade.compile(str, options); + var extname = options.client ? '.js' : '.html'; + path = path.replace(re, extname); + if (program.out) path = join(program.out, basename(path)); + var dir = resolve(dirname(path)); + mkdirp(dir, 0755, function(err){ + if (err) throw err; + var output = options.client + ? fn.toString() + : fn(options); + fs.writeFile(path, output, function(err){ + if (err) throw err; + console.log(' \033[90mrendered \033[36m%s\033[0m', path); + }); + }); + }); + // Found directory + } else if (stat.isDirectory()) { + fs.readdir(path, function(err, files) { + if (err) throw err; + files.map(function(filename) { + return path + '/' + filename; + }).forEach(renderFile); + }); + } + }); +} diff --git a/node_modules/express/.npmignore b/node_modules/express/.npmignore new file mode 100644 index 0000000..caf574d --- /dev/null +++ b/node_modules/express/.npmignore @@ -0,0 +1,9 @@ +.git* +docs/ +examples/ +support/ +test/ +testing.js +.DS_Store +coverage.html +lib-cov diff --git a/node_modules/express/.travis.yml b/node_modules/express/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/express/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/express/History.md b/node_modules/express/History.md new file mode 100644 index 0000000..1a2b171 --- /dev/null +++ b/node_modules/express/History.md @@ -0,0 +1,1091 @@ + +3.1.0 / 2013-01-25 +================== + + * add support for leading "." in "view engine" setting + * add array support to `res.set()` + * add node 0.8.x to travis.yml + * add "subdomain offset" setting for tweaking `req.subdomains` + * add `res.location(url)` implementing `res.redirect()`-like setting of Location + * use app.get() for x-powered-by setting for inheritance + * fix colons in passwords for `req.auth` + +3.0.6 / 2013-01-04 +================== + + * add http verb methods to Router + * update connect + * fix mangling of the `res.cookie()` options object + * fix jsonp whitespace escape. Closes #1132 + +3.0.5 / 2012-12-19 +================== + + * add throwing when a non-function is passed to a route + * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses + * revert "add 'etag' option" + +3.0.4 / 2012-12-05 +================== + + * add 'etag' option to disable `res.send()` Etags + * add escaping of urls in text/plain in `res.redirect()` + for old browsers interpreting as html + * change crc32 module for a more liberal license + * update connect + +3.0.3 / 2012-11-13 +================== + + * update connect + * update cookie module + * fix cookie max-age + +3.0.2 / 2012-11-08 +================== + + * add OPTIONS to cors example. Closes #1398 + * fix route chaining regression. Closes #1397 + +3.0.1 / 2012-11-01 +================== + + * update connect + +3.0.0 / 2012-10-23 +================== + + * add `make clean` + * add "Basic" check to req.auth + * add `req.auth` test coverage + * add cb && cb(payload) to `res.jsonp()`. Closes #1374 + * add backwards compat for `res.redirect()` status. Closes #1336 + * add support for `res.json()` to retain previously defined Content-Types. Closes #1349 + * update connect + * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382 + * remove non-primitive string support for `res.send()` + * fix view-locals example. Closes #1370 + * fix route-separation example + +3.0.0rc5 / 2012-09-18 +================== + + * update connect + * add redis search example + * add static-files example + * add "x-powered-by" setting (`app.disable('x-powered-by')`) + * add "application/octet-stream" redirect Accept test case. Closes #1317 + +3.0.0rc4 / 2012-08-30 +================== + + * add `res.jsonp()`. Closes #1307 + * add "verbose errors" option to error-pages example + * add another route example to express(1) so people are not so confused + * add redis online user activity tracking example + * update connect dep + * fix etag quoting. Closes #1310 + * fix error-pages 404 status + * fix jsonp callback char restrictions + * remove old OPTIONS default response + +3.0.0rc3 / 2012-08-13 +================== + + * update connect dep + * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds] + * fix `res.render()` clobbering of "locals" + +3.0.0rc2 / 2012-08-03 +================== + + * add CORS example + * update connect dep + * deprecate `.createServer()` & remove old stale examples + * fix: escape `res.redirect()` link + * fix vhost example + +3.0.0rc1 / 2012-07-24 +================== + + * add more examples to view-locals + * add scheme-relative redirects (`res.redirect("//foo.com")`) support + * update cookie dep + * update connect dep + * update send dep + * fix `express(1)` -h flag, use -H for hogan. Closes #1245 + * fix `res.sendfile()` socket error handling regression + +3.0.0beta7 / 2012-07-16 +================== + + * update connect dep for `send()` root normalization regression + +3.0.0beta6 / 2012-07-13 +================== + + * add `err.view` property for view errors. Closes #1226 + * add "jsonp callback name" setting + * add support for "/foo/:bar*" non-greedy matches + * change `res.sendfile()` to use `send()` module + * change `res.send` to use "response-send" module + * remove `app.locals.use` and `res.locals.use`, use regular middleware + +3.0.0beta5 / 2012-07-03 +================== + + * add "make check" support + * add route-map example + * add `res.json(obj, status)` support back for BC + * add "methods" dep, remove internal methods module + * update connect dep + * update auth example to utilize cores pbkdf2 + * updated tests to use "supertest" + +3.0.0beta4 / 2012-06-25 +================== + + * Added `req.auth` + * Added `req.range(size)` + * Added `res.links(obj)` + * Added `res.send(body, status)` support back for backwards compat + * Added `.default()` support to `res.format()` + * Added 2xx / 304 check to `req.fresh` + * Revert "Added + support to the router" + * Fixed `res.send()` freshness check, respect res.statusCode + +3.0.0beta3 / 2012-06-15 +================== + + * Added hogan `--hjs` to express(1) [nullfirm] + * Added another example to content-negotiation + * Added `fresh` dep + * Changed: `res.send()` always checks freshness + * Fixed: expose connects mime module. Cloases #1165 + +3.0.0beta2 / 2012-06-06 +================== + + * Added `+` support to the router + * Added `req.host` + * Changed `req.param()` to check route first + * Update connect dep + +3.0.0beta1 / 2012-06-01 +================== + + * Added `res.format()` callback to override default 406 behaviour + * Fixed `res.redirect()` 406. Closes #1154 + +3.0.0alpha5 / 2012-05-30 +================== + + * Added `req.ip` + * Added `{ signed: true }` option to `res.cookie()` + * Removed `res.signedCookie()` + * Changed: dont reverse `req.ips` + * Fixed "trust proxy" setting check for `req.ips` + +3.0.0alpha4 / 2012-05-09 +================== + + * Added: allow `[]` in jsonp callback. Closes #1128 + * Added `PORT` env var support in generated template. Closes #1118 [benatkin] + * Updated: connect 2.2.2 + +3.0.0alpha3 / 2012-05-04 +================== + + * Added public `app.routes`. Closes #887 + * Added _view-locals_ example + * Added _mvc_ example + * Added `res.locals.use()`. Closes #1120 + * Added conditional-GET support to `res.send()` + * Added: coerce `res.set()` values to strings + * Changed: moved `static()` in generated apps below router + * Changed: `res.send()` only set ETag when not previously set + * Changed connect 2.2.1 dep + * Changed: `make test` now runs unit / acceptance tests + * Fixed req/res proto inheritance + +3.0.0alpha2 / 2012-04-26 +================== + + * Added `make benchmark` back + * Added `res.send()` support for `String` objects + * Added client-side data exposing example + * Added `res.header()` and `req.header()` aliases for BC + * Added `express.createServer()` for BC + * Perf: memoize parsed urls + * Perf: connect 2.2.0 dep + * Changed: make `expressInit()` middleware self-aware + * Fixed: use app.get() for all core settings + * Fixed redis session example + * Fixed session example. Closes #1105 + * Fixed generated express dep. Closes #1078 + +3.0.0alpha1 / 2012-04-15 +================== + + * Added `app.locals.use(callback)` + * Added `app.locals` object + * Added `app.locals(obj)` + * Added `res.locals` object + * Added `res.locals(obj)` + * Added `res.format()` for content-negotiation + * Added `app.engine()` + * Added `res.cookie()` JSON cookie support + * Added "trust proxy" setting + * Added `req.subdomains` + * Added `req.protocol` + * Added `req.secure` + * Added `req.path` + * Added `req.ips` + * Added `req.fresh` + * Added `req.stale` + * Added comma-delmited / array support for `req.accepts()` + * Added debug instrumentation + * Added `res.set(obj)` + * Added `res.set(field, value)` + * Added `res.get(field)` + * Added `app.get(setting)`. Closes #842 + * Added `req.acceptsLanguage()` + * Added `req.acceptsCharset()` + * Added `req.accepted` + * Added `req.acceptedLanguages` + * Added `req.acceptedCharsets` + * Added "json replacer" setting + * Added "json spaces" setting + * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92 + * Added `--less` support to express(1) + * Added `express.response` prototype + * Added `express.request` prototype + * Added `express.application` prototype + * Added `app.path()` + * Added `app.render()` + * Added `res.type()` to replace `res.contentType()` + * Changed: `res.redirect()` to add relative support + * Changed: enable "jsonp callback" by default + * Changed: renamed "case sensitive routes" to "case sensitive routing" + * Rewrite of all tests with mocha + * Removed "root" setting + * Removed `res.redirect('home')` support + * Removed `req.notify()` + * Removed `app.register()` + * Removed `app.redirect()` + * Removed `app.is()` + * Removed `app.helpers()` + * Removed `app.dynamicHelpers()` + * Fixed `res.sendfile()` with non-GET. Closes #723 + * Fixed express(1) public dir for windows. Closes #866 + +2.5.9/ 2012-04-02 +================== + + * Added support for PURGE request method [pbuyle] + * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki] + +2.5.8 / 2012-02-08 +================== + + * Update mkdirp dep. Closes #991 + +2.5.7 / 2012-02-06 +================== + + * Fixed `app.all` duplicate DELETE requests [mscdex] + +2.5.6 / 2012-01-13 +================== + + * Updated hamljs dev dep. Closes #953 + +2.5.5 / 2012-01-08 +================== + + * Fixed: set `filename` on cached templates [matthewleon] + +2.5.4 / 2012-01-02 +================== + + * Fixed `express(1)` eol on 0.4.x. Closes #947 + +2.5.3 / 2011-12-30 +================== + + * Fixed `req.is()` when a charset is present + +2.5.2 / 2011-12-10 +================== + + * Fixed: express(1) LF -> CRLF for windows + +2.5.1 / 2011-11-17 +================== + + * Changed: updated connect to 1.8.x + * Removed sass.js support from express(1) + +2.5.0 / 2011-10-24 +================== + + * Added ./routes dir for generated app by default + * Added npm install reminder to express(1) app gen + * Added 0.5.x support + * Removed `make test-cov` since it wont work with node 0.5.x + * Fixed express(1) public dir for windows. Closes #866 + +2.4.7 / 2011-10-05 +================== + + * Added mkdirp to express(1). Closes #795 + * Added simple _json-config_ example + * Added shorthand for the parsed request's pathname via `req.path` + * Changed connect dep to 1.7.x to fix npm issue... + * Fixed `res.redirect()` __HEAD__ support. [reported by xerox] + * Fixed `req.flash()`, only escape args + * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] + +2.4.6 / 2011-08-22 +================== + + * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] + +2.4.5 / 2011-08-19 +================== + + * Added support for routes to handle errors. Closes #809 + * Added `app.routes.all()`. Closes #803 + * Added "basepath" setting to work in conjunction with reverse proxies etc. + * Refactored `Route` to use a single array of callbacks + * Added support for multiple callbacks for `app.param()`. Closes #801 +Closes #805 + * Changed: removed .call(self) for route callbacks + * Dependency: `qs >= 0.3.1` + * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808 + +2.4.4 / 2011-08-05 +================== + + * Fixed `res.header()` intention of a set, even when `undefined` + * Fixed `*`, value no longer required + * Fixed `res.send(204)` support. Closes #771 + +2.4.3 / 2011-07-14 +================== + + * Added docs for `status` option special-case. Closes #739 + * Fixed `options.filename`, exposing the view path to template engines + +2.4.2. / 2011-07-06 +================== + + * Revert "removed jsonp stripping" for XSS + +2.4.1 / 2011-07-06 +================== + + * Added `res.json()` JSONP support. Closes #737 + * Added _extending-templates_ example. Closes #730 + * Added "strict routing" setting for trailing slashes + * Added support for multiple envs in `app.configure()` calls. Closes #735 + * Changed: `res.send()` using `res.json()` + * Changed: when cookie `path === null` don't default it + * Changed; default cookie path to "home" setting. Closes #731 + * Removed _pids/logs_ creation from express(1) + +2.4.0 / 2011-06-28 +================== + + * Added chainable `res.status(code)` + * Added `res.json()`, an explicit version of `res.send(obj)` + * Added simple web-service example + +2.3.12 / 2011-06-22 +================== + + * \#express is now on freenode! come join! + * Added `req.get(field, param)` + * Added links to Japanese documentation, thanks @hideyukisaito! + * Added; the `express(1)` generated app outputs the env + * Added `content-negotiation` example + * Dependency: connect >= 1.5.1 < 2.0.0 + * Fixed view layout bug. Closes #720 + * Fixed; ignore body on 304. Closes #701 + +2.3.11 / 2011-06-04 +================== + + * Added `npm test` + * Removed generation of dummy test file from `express(1)` + * Fixed; `express(1)` adds express as a dep + * Fixed; prune on `prepublish` + +2.3.10 / 2011-05-27 +================== + + * Added `req.route`, exposing the current route + * Added _package.json_ generation support to `express(1)` + * Fixed call to `app.param()` function for optional params. Closes #682 + +2.3.9 / 2011-05-25 +================== + + * Fixed bug-ish with `../' in `res.partial()` calls + +2.3.8 / 2011-05-24 +================== + + * Fixed `app.options()` + +2.3.7 / 2011-05-23 +================== + + * Added route `Collection`, ex: `app.get('/user/:id').remove();` + * Added support for `app.param(fn)` to define param logic + * Removed `app.param()` support for callback with return value + * Removed module.parent check from express(1) generated app. Closes #670 + * Refactored router. Closes #639 + +2.3.6 / 2011-05-20 +================== + + * Changed; using devDependencies instead of git submodules + * Fixed redis session example + * Fixed markdown example + * Fixed view caching, should not be enabled in development + +2.3.5 / 2011-05-20 +================== + + * Added export `.view` as alias for `.View` + +2.3.4 / 2011-05-08 +================== + + * Added `./examples/say` + * Fixed `res.sendfile()` bug preventing the transfer of files with spaces + +2.3.3 / 2011-05-03 +================== + + * Added "case sensitive routes" option. + * Changed; split methods supported per rfc [slaskis] + * Fixed route-specific middleware when using the same callback function several times + +2.3.2 / 2011-04-27 +================== + + * Fixed view hints + +2.3.1 / 2011-04-26 +================== + + * Added `app.match()` as `app.match.all()` + * Added `app.lookup()` as `app.lookup.all()` + * Added `app.remove()` for `app.remove.all()` + * Added `app.remove.VERB()` + * Fixed template caching collision issue. Closes #644 + * Moved router over from connect and started refactor + +2.3.0 / 2011-04-25 +================== + + * Added options support to `res.clearCookie()` + * Added `res.helpers()` as alias of `res.locals()` + * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0` + * Changed; auto set Content-Type in res.attachement [Aaron Heckmann] + * Renamed "cache views" to "view cache". Closes #628 + * Fixed caching of views when using several apps. Closes #637 + * Fixed gotcha invoking `app.param()` callbacks once per route middleware. +Closes #638 + * Fixed partial lookup precedence. Closes #631 +Shaw] + +2.2.2 / 2011-04-12 +================== + + * Added second callback support for `res.download()` connection errors + * Fixed `filename` option passing to template engine + +2.2.1 / 2011-04-04 +================== + + * Added `layout(path)` helper to change the layout within a view. Closes #610 + * Fixed `partial()` collection object support. + Previously only anything with `.length` would work. + When `.length` is present one must still be aware of holes, + however now `{ collection: {foo: 'bar'}}` is valid, exposes + `keyInCollection` and `keysInCollection`. + + * Performance improved with better view caching + * Removed `request` and `response` locals + * Changed; errorHandler page title is now `Express` instead of `Connect` + +2.2.0 / 2011-03-30 +================== + + * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606 + * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606 + * Added `app.VERB(path)` as alias of `app.lookup.VERB()`. + * Dependency `connect >= 1.2.0` + +2.1.1 / 2011-03-29 +================== + + * Added; expose `err.view` object when failing to locate a view + * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann] + * Fixed; `res.send(undefined)` responds with 204 [aheckmann] + +2.1.0 / 2011-03-24 +================== + + * Added `/_?` partial lookup support. Closes #447 + * Added `request`, `response`, and `app` local variables + * Added `settings` local variable, containing the app's settings + * Added `req.flash()` exception if `req.session` is not available + * Added `res.send(bool)` support (json response) + * Fixed stylus example for latest version + * Fixed; wrap try/catch around `res.render()` + +2.0.0 / 2011-03-17 +================== + + * Fixed up index view path alternative. + * Changed; `res.locals()` without object returns the locals + +2.0.0rc3 / 2011-03-17 +================== + + * Added `res.locals(obj)` to compliment `res.local(key, val)` + * Added `res.partial()` callback support + * Fixed recursive error reporting issue in `res.render()` + +2.0.0rc2 / 2011-03-17 +================== + + * Changed; `partial()` "locals" are now optional + * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01] + * Fixed .filename view engine option [reported by drudge] + * Fixed blog example + * Fixed `{req,res}.app` reference when mounting [Ben Weaver] + +2.0.0rc / 2011-03-14 +================== + + * Fixed; expose `HTTPSServer` constructor + * Fixed express(1) default test charset. Closes #579 [reported by secoif] + * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP] + +2.0.0beta3 / 2011-03-09 +================== + + * Added support for `res.contentType()` literal + The original `res.contentType('.json')`, + `res.contentType('application/json')`, and `res.contentType('json')` + will work now. + * Added `res.render()` status option support back + * Added charset option for `res.render()` + * Added `.charset` support (via connect 1.0.4) + * Added view resolution hints when in development and a lookup fails + * Added layout lookup support relative to the page view. + For example while rendering `./views/user/index.jade` if you create + `./views/user/layout.jade` it will be used in favour of the root layout. + * Fixed `res.redirect()`. RFC states absolute url [reported by unlink] + * Fixed; default `res.send()` string charset to utf8 + * Removed `Partial` constructor (not currently used) + +2.0.0beta2 / 2011-03-07 +================== + + * Added res.render() `.locals` support back to aid in migration process + * Fixed flash example + +2.0.0beta / 2011-03-03 +================== + + * Added HTTPS support + * Added `res.cookie()` maxAge support + * Added `req.header()` _Referrer_ / _Referer_ special-case, either works + * Added mount support for `res.redirect()`, now respects the mount-point + * Added `union()` util, taking place of `merge(clone())` combo + * Added stylus support to express(1) generated app + * Added secret to session middleware used in examples and generated app + * Added `res.local(name, val)` for progressive view locals + * Added default param support to `req.param(name, default)` + * Added `app.disabled()` and `app.enabled()` + * Added `app.register()` support for omitting leading ".", either works + * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539 + * Added `app.param()` to map route params to async/sync logic + * Added; aliased `app.helpers()` as `app.locals()`. Closes #481 + * Added extname with no leading "." support to `res.contentType()` + * Added `cache views` setting, defaulting to enabled in "production" env + * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_. + * Added `req.accepts()` support for extensions + * Changed; `res.download()` and `res.sendfile()` now utilize Connect's + static file server `connect.static.send()`. + * Changed; replaced `connect.utils.mime()` with npm _mime_ module + * Changed; allow `req.query` to be pre-defined (via middleware or other parent + * Changed view partial resolution, now relative to parent view + * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`. + * Fixed `req.param()` bug returning Array.prototype methods. Closes #552 + * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()` + * Fixed; using _qs_ module instead of _querystring_ + * Fixed; strip unsafe chars from jsonp callbacks + * Removed "stream threshold" setting + +1.0.8 / 2011-03-01 +================== + + * Allow `req.query` to be pre-defined (via middleware or other parent app) + * "connect": ">= 0.5.0 < 1.0.0". Closes #547 + * Removed the long deprecated __EXPRESS_ENV__ support + +1.0.7 / 2011-02-07 +================== + + * Fixed `render()` setting inheritance. + Mounted apps would not inherit "view engine" + +1.0.6 / 2011-02-07 +================== + + * Fixed `view engine` setting bug when period is in dirname + +1.0.5 / 2011-02-05 +================== + + * Added secret to generated app `session()` call + +1.0.4 / 2011-02-05 +================== + + * Added `qs` dependency to _package.json_ + * Fixed namespaced `require()`s for latest connect support + +1.0.3 / 2011-01-13 +================== + + * Remove unsafe characters from JSONP callback names [Ryan Grove] + +1.0.2 / 2011-01-10 +================== + + * Removed nested require, using `connect.router` + +1.0.1 / 2010-12-29 +================== + + * Fixed for middleware stacked via `createServer()` + previously the `foo` middleware passed to `createServer(foo)` + would not have access to Express methods such as `res.send()` + or props like `req.query` etc. + +1.0.0 / 2010-11-16 +================== + + * Added; deduce partial object names from the last segment. + For example by default `partial('forum/post', postObject)` will + give you the _post_ object, providing a meaningful default. + * Added http status code string representation to `res.redirect()` body + * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__. + * Added `req.is()` to aid in content negotiation + * Added partial local inheritance [suggested by masylum]. Closes #102 + providing access to parent template locals. + * Added _-s, --session[s]_ flag to express(1) to add session related middleware + * Added _--template_ flag to express(1) to specify the + template engine to use. + * Added _--css_ flag to express(1) to specify the + stylesheet engine to use (or just plain css by default). + * Added `app.all()` support [thanks aheckmann] + * Added partial direct object support. + You may now `partial('user', user)` providing the "user" local, + vs previously `partial('user', { object: user })`. + * Added _route-separation_ example since many people question ways + to do this with CommonJS modules. Also view the _blog_ example for + an alternative. + * Performance; caching view path derived partial object names + * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454 + * Fixed jsonp support; _text/javascript_ as per mailinglist discussion + +1.0.0rc4 / 2010-10-14 +================== + + * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0 + * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware)) + * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass] + * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass] + * Added `partial()` support for array-like collections. Closes #434 + * Added support for swappable querystring parsers + * Added session usage docs. Closes #443 + * Added dynamic helper caching. Closes #439 [suggested by maritz] + * Added authentication example + * Added basic Range support to `res.sendfile()` (and `res.download()` etc) + * Changed; `express(1)` generated app using 2 spaces instead of 4 + * Default env to "development" again [aheckmann] + * Removed _context_ option is no more, use "scope" + * Fixed; exposing _./support_ libs to examples so they can run without installs + * Fixed mvc example + +1.0.0rc3 / 2010-09-20 +================== + + * Added confirmation for `express(1)` app generation. Closes #391 + * Added extending of flash formatters via `app.flashFormatters` + * Added flash formatter support. Closes #411 + * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold" + * Added _stream threshold_ setting for `res.sendfile()` + * Added `res.send()` __HEAD__ support + * Added `res.clearCookie()` + * Added `res.cookie()` + * Added `res.render()` headers option + * Added `res.redirect()` response bodies + * Added `res.render()` status option support. Closes #425 [thanks aheckmann] + * Fixed `res.sendfile()` responding with 403 on malicious path + * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_ + * Fixed; mounted apps settings now inherit from parent app [aheckmann] + * Fixed; stripping Content-Length / Content-Type when 204 + * Fixed `res.send()` 204. Closes #419 + * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402 + * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo] + + +1.0.0rc2 / 2010-08-17 +================== + + * Added `app.register()` for template engine mapping. Closes #390 + * Added `res.render()` callback support as second argument (no options) + * Added callback support to `res.download()` + * Added callback support for `res.sendfile()` + * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()` + * Added "partials" setting to docs + * Added default expresso tests to `express(1)` generated app. Closes #384 + * Fixed `res.sendfile()` error handling, defer via `next()` + * Fixed `res.render()` callback when a layout is used [thanks guillermo] + * Fixed; `make install` creating ~/.node_libraries when not present + * Fixed issue preventing error handlers from being defined anywhere. Closes #387 + +1.0.0rc / 2010-07-28 +================== + + * Added mounted hook. Closes #369 + * Added connect dependency to _package.json_ + + * Removed "reload views" setting and support code + development env never caches, production always caches. + + * Removed _param_ in route callbacks, signature is now + simply (req, res, next), previously (req, res, params, next). + Use _req.params_ for path captures, _req.query_ for GET params. + + * Fixed "home" setting + * Fixed middleware/router precedence issue. Closes #366 + * Fixed; _configure()_ callbacks called immediately. Closes #368 + +1.0.0beta2 / 2010-07-23 +================== + + * Added more examples + * Added; exporting `Server` constructor + * Added `Server#helpers()` for view locals + * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349 + * Added support for absolute view paths + * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363 + * Added Guillermo Rauch to the contributor list + * Added support for "as" for non-collection partials. Closes #341 + * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf] + * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo] + * Fixed instanceof `Array` checks, now `Array.isArray()` + * Fixed express(1) expansion of public dirs. Closes #348 + * Fixed middleware precedence. Closes #345 + * Fixed view watcher, now async [thanks aheckmann] + +1.0.0beta / 2010-07-15 +================== + + * Re-write + - much faster + - much lighter + - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs + +0.14.0 / 2010-06-15 +================== + + * Utilize relative requires + * Added Static bufferSize option [aheckmann] + * Fixed caching of view and partial subdirectories [aheckmann] + * Fixed mime.type() comments now that ".ext" is not supported + * Updated haml submodule + * Updated class submodule + * Removed bin/express + +0.13.0 / 2010-06-01 +================== + + * Added node v0.1.97 compatibility + * Added support for deleting cookies via Request#cookie('key', null) + * Updated haml submodule + * Fixed not-found page, now using using charset utf-8 + * Fixed show-exceptions page, now using using charset utf-8 + * Fixed view support due to fs.readFile Buffers + * Changed; mime.type() no longer accepts ".type" due to node extname() changes + +0.12.0 / 2010-05-22 +================== + + * Added node v0.1.96 compatibility + * Added view `helpers` export which act as additional local variables + * Updated haml submodule + * Changed ETag; removed inode, modified time only + * Fixed LF to CRLF for setting multiple cookies + * Fixed cookie complation; values are now urlencoded + * Fixed cookies parsing; accepts quoted values and url escaped cookies + +0.11.0 / 2010-05-06 +================== + + * Added support for layouts using different engines + - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' }) + - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml' + - this.render('page.html.haml', { layout: false }) // no layout + * Updated ext submodule + * Updated haml submodule + * Fixed EJS partial support by passing along the context. Issue #307 + +0.10.1 / 2010-05-03 +================== + + * Fixed binary uploads. + +0.10.0 / 2010-04-30 +================== + + * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s + encoding is set to 'utf8' or 'utf-8'. + * Added "encoding" option to Request#render(). Closes #299 + * Added "dump exceptions" setting, which is enabled by default. + * Added simple ejs template engine support + * Added error reponse support for text/plain, application/json. Closes #297 + * Added callback function param to Request#error() + * Added Request#sendHead() + * Added Request#stream() + * Added support for Request#respond(304, null) for empty response bodies + * Added ETag support to Request#sendfile() + * Added options to Request#sendfile(), passed to fs.createReadStream() + * Added filename arg to Request#download() + * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request + * Performance enhanced by preventing several calls to toLowerCase() in Router#match() + * Changed; Request#sendfile() now streams + * Changed; Renamed Request#halt() to Request#respond(). Closes #289 + * Changed; Using sys.inspect() instead of JSON.encode() for error output + * Changed; run() returns the http.Server instance. Closes #298 + * Changed; Defaulting Server#host to null (INADDR_ANY) + * Changed; Logger "common" format scale of 0.4f + * Removed Logger "request" format + * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found + * Fixed several issues with http client + * Fixed Logger Content-Length output + * Fixed bug preventing Opera from retaining the generated session id. Closes #292 + +0.9.0 / 2010-04-14 +================== + + * Added DSL level error() route support + * Added DSL level notFound() route support + * Added Request#error() + * Added Request#notFound() + * Added Request#render() callback function. Closes #258 + * Added "max upload size" setting + * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254 + * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js + * Added callback function support to Request#halt() as 3rd/4th arg + * Added preprocessing of route param wildcards using param(). Closes #251 + * Added view partial support (with collections etc) + * Fixed bug preventing falsey params (such as ?page=0). Closes #286 + * Fixed setting of multiple cookies. Closes #199 + * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml) + * Changed; session cookie is now httpOnly + * Changed; Request is no longer global + * Changed; Event is no longer global + * Changed; "sys" module is no longer global + * Changed; moved Request#download to Static plugin where it belongs + * Changed; Request instance created before body parsing. Closes #262 + * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253 + * Changed; Pre-caching view partials in memory when "cache view partials" is enabled + * Updated support to node --version 0.1.90 + * Updated dependencies + * Removed set("session cookie") in favour of use(Session, { cookie: { ... }}) + * Removed utils.mixin(); use Object#mergeDeep() + +0.8.0 / 2010-03-19 +================== + + * Added coffeescript example app. Closes #242 + * Changed; cache api now async friendly. Closes #240 + * Removed deprecated 'express/static' support. Use 'express/plugins/static' + +0.7.6 / 2010-03-19 +================== + + * Added Request#isXHR. Closes #229 + * Added `make install` (for the executable) + * Added `express` executable for setting up simple app templates + * Added "GET /public/*" to Static plugin, defaulting to /public + * Added Static plugin + * Fixed; Request#render() only calls cache.get() once + * Fixed; Namespacing View caches with "view:" + * Fixed; Namespacing Static caches with "static:" + * Fixed; Both example apps now use the Static plugin + * Fixed set("views"). Closes #239 + * Fixed missing space for combined log format + * Deprecated Request#sendfile() and 'express/static' + * Removed Server#running + +0.7.5 / 2010-03-16 +================== + + * Added Request#flash() support without args, now returns all flashes + * Updated ext submodule + +0.7.4 / 2010-03-16 +================== + + * Fixed session reaper + * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft) + +0.7.3 / 2010-03-16 +================== + + * Added package.json + * Fixed requiring of haml / sass due to kiwi removal + +0.7.2 / 2010-03-16 +================== + + * Fixed GIT submodules (HAH!) + +0.7.1 / 2010-03-16 +================== + + * Changed; Express now using submodules again until a PM is adopted + * Changed; chat example using millisecond conversions from ext + +0.7.0 / 2010-03-15 +================== + + * Added Request#pass() support (finds the next matching route, or the given path) + * Added Logger plugin (default "common" format replaces CommonLogger) + * Removed Profiler plugin + * Removed CommonLogger plugin + +0.6.0 / 2010-03-11 +================== + + * Added seed.yml for kiwi package management support + * Added HTTP client query string support when method is GET. Closes #205 + + * Added support for arbitrary view engines. + For example "foo.engine.html" will now require('engine'), + the exports from this module are cached after the first require(). + + * Added async plugin support + + * Removed usage of RESTful route funcs as http client + get() etc, use http.get() and friends + + * Removed custom exceptions + +0.5.0 / 2010-03-10 +================== + + * Added ext dependency (library of js extensions) + * Removed extname() / basename() utils. Use path module + * Removed toArray() util. Use arguments.values + * Removed escapeRegexp() util. Use RegExp.escape() + * Removed process.mixin() dependency. Use utils.mixin() + * Removed Collection + * Removed ElementCollection + * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;) + +0.4.0 / 2010-02-11 +================== + + * Added flash() example to sample upload app + * Added high level restful http client module (express/http) + * Changed; RESTful route functions double as HTTP clients. Closes #69 + * Changed; throwing error when routes are added at runtime + * Changed; defaulting render() context to the current Request. Closes #197 + * Updated haml submodule + +0.3.0 / 2010-02-11 +================== + + * Updated haml / sass submodules. Closes #200 + * Added flash message support. Closes #64 + * Added accepts() now allows multiple args. fixes #117 + * Added support for plugins to halt. Closes #189 + * Added alternate layout support. Closes #119 + * Removed Route#run(). Closes #188 + * Fixed broken specs due to use(Cookie) missing + +0.2.1 / 2010-02-05 +================== + + * Added "plot" format option for Profiler (for gnuplot processing) + * Added request number to Profiler plugin + * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8 + * Fixed issue with routes not firing when not files are present. Closes #184 + * Fixed process.Promise -> events.Promise + +0.2.0 / 2010-02-03 +================== + + * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180 + * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174 + * Added expiration support to cache api with reaper. Closes #133 + * Added cache Store.Memory#reap() + * Added Cache; cache api now uses first class Cache instances + * Added abstract session Store. Closes #172 + * Changed; cache Memory.Store#get() utilizing Collection + * Renamed MemoryStore -> Store.Memory + * Fixed use() of the same plugin several time will always use latest options. Closes #176 + +0.1.0 / 2010-02-03 +================== + + * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context + * Updated node support to 0.1.27 Closes #169 + * Updated dirname(__filename) -> __dirname + * Updated libxmljs support to v0.2.0 + * Added session support with memory store / reaping + * Added quick uid() helper + * Added multi-part upload support + * Added Sass.js support / submodule + * Added production env caching view contents and static files + * Added static file caching. Closes #136 + * Added cache plugin with memory stores + * Added support to StaticFile so that it works with non-textual files. + * Removed dirname() helper + * Removed several globals (now their modules must be required) + +0.0.2 / 2010-01-10 +================== + + * Added view benchmarks; currently haml vs ejs + * Added Request#attachment() specs. Closes #116 + * Added use of node's parseQuery() util. Closes #123 + * Added `make init` for submodules + * Updated Haml + * Updated sample chat app to show messages on load + * Updated libxmljs parseString -> parseHtmlString + * Fixed `make init` to work with older versions of git + * Fixed specs can now run independant specs for those who cant build deps. Closes #127 + * Fixed issues introduced by the node url module changes. Closes 126. + * Fixed two assertions failing due to Collection#keys() returning strings + * Fixed faulty Collection#toArray() spec due to keys() returning strings + * Fixed `make test` now builds libxmljs.node before testing + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/LICENSE b/node_modules/express/LICENSE new file mode 100644 index 0000000..36075a3 --- /dev/null +++ b/node_modules/express/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2009-2011 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/express/Makefile b/node_modules/express/Makefile new file mode 100644 index 0000000..e820e31 --- /dev/null +++ b/node_modules/express/Makefile @@ -0,0 +1,33 @@ + +MOCHA_OPTS= +REPORTER = dot + +check: test + +test: test-unit test-acceptance + +test-unit: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + $(MOCHA_OPTS) + +test-acceptance: + @NODE_ENV=test ./node_modules/.bin/mocha \ + --reporter $(REPORTER) \ + --bail \ + test/acceptance/*.js + +test-cov: lib-cov + @EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html + +lib-cov: + @jscoverage lib lib-cov + +benchmark: + @./support/bench + +clean: + rm -f coverage.html + rm -fr lib-cov + +.PHONY: test test-unit test-acceptance benchmark clean diff --git a/node_modules/express/Readme.md b/node_modules/express/Readme.md new file mode 100644 index 0000000..6bb8b95 --- /dev/null +++ b/node_modules/express/Readme.md @@ -0,0 +1,179 @@ +![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png) + + Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) + +```js +var express = require('express'); +var app = express(); + +app.get('/', function(req, res){ + res.send('Hello World'); +}); + +app.listen(3000); +``` + +## Installation + + $ npm install -g express + +## Quick Start + + The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below: + + Create the app: + + $ npm install -g express + $ express /tmp/foo && cd /tmp/foo + + Install dependencies: + + $ npm install + + Start the server: + + $ node app + +## Features + + * Built on [Connect](http://github.com/senchalabs/connect) + * Robust routing + * HTTP helpers (redirection, caching, etc) + * View system supporting 14+ template engines + * Content negotiation + * Focus on high performance + * Environment based configuration + * Executable for generating applications quickly + * High test coverage + +## Philosophy + + The Express philosophy is to provide small, robust tooling for HTTP servers. Making + it a great solution for single page applications, web sites, hybrids, or public + HTTP APIs. + + Built on Connect you can use _only_ what you need, and nothing more, applications + can be as big or as small as you like, even a single file. Express does + not force you to use any specific ORM or template engine. With support for over + 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js) + you can quickly craft your perfect framework. + +## More Information + + * Join #express on freenode + * [Google Group](http://groups.google.com/group/express-js) for discussion + * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates + * Visit the [Wiki](http://github.com/visionmedia/express/wiki) + * [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito) + * [Русскоязычная документация](http://express-js.ru/) + +## Viewing Examples + +Clone the Express repo, then install the dev dependencies to install all the example / test suite deps: + + $ git clone git://github.com/visionmedia/express.git --depth 1 + $ cd express + $ npm install + +then run whichever tests you want: + + $ node examples/content-negotiation + +## Running Tests + +To run the test suite first invoke the following command within the repo, installing the development dependencies: + + $ npm install + +then run the tests: + + $ make test + +## Contributors + +``` +project: express +commits: 3559 +active : 468 days +files : 237 +authors: + 1891 Tj Holowaychuk 53.1% + 1285 visionmedia 36.1% + 182 TJ Holowaychuk 5.1% + 54 Aaron Heckmann 1.5% + 34 csausdev 1.0% + 26 ciaranj 0.7% + 21 Robert Sköld 0.6% + 6 Guillermo Rauch 0.2% + 3 Dav Glass 0.1% + 3 Nick Poulden 0.1% + 2 Randy Merrill 0.1% + 2 Benny Wong 0.1% + 2 Hunter Loftis 0.1% + 2 Jake Gordon 0.1% + 2 Brian McKinney 0.1% + 2 Roman Shtylman 0.1% + 2 Ben Weaver 0.1% + 2 Dave Hoover 0.1% + 2 Eivind Fjeldstad 0.1% + 2 Daniel Shaw 0.1% + 1 Matt Colyer 0.0% + 1 Pau Ramon 0.0% + 1 Pero Pejovic 0.0% + 1 Peter Rekdal Sunde 0.0% + 1 Raynos 0.0% + 1 Teng Siong Ong 0.0% + 1 Viktor Kelemen 0.0% + 1 ctide 0.0% + 1 8bitDesigner 0.0% + 1 isaacs 0.0% + 1 mgutz 0.0% + 1 pikeas 0.0% + 1 shuwatto 0.0% + 1 tstrimple 0.0% + 1 ewoudj 0.0% + 1 Adam Sanderson 0.0% + 1 Andrii Kostenko 0.0% + 1 Andy Hiew 0.0% + 1 Arpad Borsos 0.0% + 1 Ashwin Purohit 0.0% + 1 Benjen 0.0% + 1 Darren Torpey 0.0% + 1 Greg Ritter 0.0% + 1 Gregory Ritter 0.0% + 1 James Herdman 0.0% + 1 Jim Snodgrass 0.0% + 1 Joe McCann 0.0% + 1 Jonathan Dumaine 0.0% + 1 Jonathan Palardy 0.0% + 1 Jonathan Zacsh 0.0% + 1 Justin Lilly 0.0% + 1 Ken Sato 0.0% + 1 Maciej Małecki 0.0% + 1 Masahiro Hayashi 0.0% +``` + +## License + +(The MIT License) + +Copyright (c) 2009-2012 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. diff --git a/node_modules/express/bin/express b/node_modules/express/bin/express new file mode 100755 index 0000000..3c0090c --- /dev/null +++ b/node_modules/express/bin/express @@ -0,0 +1,422 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var exec = require('child_process').exec + , program = require('commander') + , mkdirp = require('mkdirp') + , pkg = require('../package.json') + , version = pkg.version + , os = require('os') + , fs = require('fs'); + +// CLI + +program + .version(version) + .option('-s, --sessions', 'add session support') + .option('-e, --ejs', 'add ejs engine support (defaults to jade)') + .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)') + .option('-H, --hogan', 'add hogan.js engine support') + .option('-c, --css ', 'add stylesheet support (less|stylus) (defaults to plain css)') + .option('-f, --force', 'force on non-empty directory') + .parse(process.argv); + +// Path + +var path = program.args.shift() || '.'; + +// end-of-line code + +var eol = 'win32' == os.platform() ? '\r\n' : '\n' + +// Template engine + +program.template = 'jade'; +if (program.ejs) program.template = 'ejs'; +if (program.jshtml) program.template = 'jshtml'; +if (program.hogan) program.template = 'hjs'; + +/** + * Routes index template. + */ + +var index = [ + '' + , '/*' + , ' * GET home page.' + , ' */' + , '' + , 'exports.index = function(req, res){' + , ' res.render(\'index\', { title: \'Express\' });' + , '};' +].join(eol); + +/** + * Routes users template. + */ + +var users = [ + '' + , '/*' + , ' * GET users listing.' + , ' */' + , '' + , 'exports.list = function(req, res){' + , ' res.send("respond with a resource");' + , '};' +].join(eol); + +/** + * Jade layout template. + */ + +var jadeLayout = [ + 'doctype 5' + , 'html' + , ' head' + , ' title= title' + , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')' + , ' body' + , ' block content' +].join(eol); + +/** + * Jade index template. + */ + +var jadeIndex = [ + 'extends layout' + , '' + , 'block content' + , ' h1= title' + , ' p Welcome to #{title}' +].join(eol); + +/** + * EJS index template. + */ + +var ejsIndex = [ + '' + , '' + , ' ' + , ' <%= title %>' + , ' ' + , ' ' + , ' ' + , '

<%= title %>

' + , '

Welcome to <%= title %>

' + , ' ' + , '' +].join(eol); + +/** + * JSHTML layout template. + */ + +var jshtmlLayout = [ + '' + , '' + , ' ' + , ' @write(title) ' + , ' ' + , ' ' + , ' ' + , ' @write(body)' + , ' ' + , '' +].join(eol); + +/** + * JSHTML index template. + */ + +var jshtmlIndex = [ + '

@write(title)

' + , '

Welcome to @write(title)

' +].join(eol); + +/** + * Hogan.js index template. + */ +var hoganIndex = [ + '' + , '' + , ' ' + , ' {{ title }}' + , ' ' + , ' ' + , ' ' + , '

{{ title }}

' + , '

Welcome to {{ title }}

' + , ' ' + , '' +].join(eol); + +/** + * Default css template. + */ + +var css = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default less template. + */ + +var less = [ + 'body {' + , ' padding: 50px;' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;' + , '}' + , '' + , 'a {' + , ' color: #00B7FF;' + , '}' +].join(eol); + +/** + * Default stylus template. + */ + +var stylus = [ + 'body' + , ' padding: 50px' + , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif' + , 'a' + , ' color: #00B7FF' +].join(eol); + +/** + * App template. + */ + +var app = [ + '' + , '/**' + , ' * Module dependencies.' + , ' */' + , '' + , 'var express = require(\'express\')' + , ' , routes = require(\'./routes\')' + , ' , user = require(\'./routes/user\')' + , ' , http = require(\'http\')' + , ' , path = require(\'path\');' + , '' + , 'var app = express();' + , '' + , 'app.configure(function(){' + , ' app.set(\'port\', process.env.PORT || 3000);' + , ' app.set(\'views\', __dirname + \'/views\');' + , ' app.set(\'view engine\', \':TEMPLATE\');' + , ' app.use(express.favicon());' + , ' app.use(express.logger(\'dev\'));' + , ' app.use(express.bodyParser());' + , ' app.use(express.methodOverride());{sess}' + , ' app.use(app.router);{css}' + , ' app.use(express.static(path.join(__dirname, \'public\')));' + , '});' + , '' + , 'app.configure(\'development\', function(){' + , ' app.use(express.errorHandler());' + , '});' + , '' + , 'app.get(\'/\', routes.index);' + , 'app.get(\'/users\', user.list);' + , '' + , 'http.createServer(app).listen(app.get(\'port\'), function(){' + , ' console.log("Express server listening on port " + app.get(\'port\'));' + , '});' + , '' +].join(eol); + +// Generate application + +(function createApplication(path) { + emptyDirectory(path, function(empty){ + if (empty || program.force) { + createApplicationAt(path); + } else { + program.confirm('destination is not empty, continue? ', function(ok){ + if (ok) { + process.stdin.destroy(); + createApplicationAt(path); + } else { + abort('aborting'); + } + }); + } + }); +})(path); + +/** + * Create application at the given directory `path`. + * + * @param {String} path + */ + +function createApplicationAt(path) { + console.log(); + process.on('exit', function(){ + console.log(); + console.log(' install dependencies:'); + console.log(' $ cd %s && npm install', path); + console.log(); + console.log(' run the app:'); + console.log(' $ node app'); + console.log(); + }); + + mkdir(path, function(){ + mkdir(path + '/public'); + mkdir(path + '/public/javascripts'); + mkdir(path + '/public/images'); + mkdir(path + '/public/stylesheets', function(){ + switch (program.css) { + case 'less': + write(path + '/public/stylesheets/style.less', less); + break; + case 'stylus': + write(path + '/public/stylesheets/style.styl', stylus); + break; + default: + write(path + '/public/stylesheets/style.css', css); + } + }); + + mkdir(path + '/routes', function(){ + write(path + '/routes/index.js', index); + write(path + '/routes/user.js', users); + }); + + mkdir(path + '/views', function(){ + switch (program.template) { + case 'ejs': + write(path + '/views/index.ejs', ejsIndex); + break; + case 'jade': + write(path + '/views/layout.jade', jadeLayout); + write(path + '/views/index.jade', jadeIndex); + break; + case 'jshtml': + write(path + '/views/layout.jshtml', jshtmlLayout); + write(path + '/views/index.jshtml', jshtmlIndex); + break; + case 'hjs': + write(path + '/views/index.hjs', hoganIndex); + break; + + } + }); + + // CSS Engine support + switch (program.css) { + case 'less': + app = app.replace('{css}', eol + ' app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));'); + break; + case 'stylus': + app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware(__dirname + \'/public\'));'); + break; + default: + app = app.replace('{css}', ''); + } + + // Session support + app = app.replace('{sess}', program.sessions + ? eol + ' app.use(express.cookieParser(\'your secret here\'));' + eol + ' app.use(express.session());' + : ''); + + // Template support + app = app.replace(':TEMPLATE', program.template); + + // package.json + var pkg = { + name: 'application-name' + , version: '0.0.1' + , private: true + , scripts: { start: 'node app' } + , dependencies: { + express: version + } + } + + if (program.template) pkg.dependencies[program.template] = '*'; + + // CSS Engine support + switch (program.css) { + case 'less': + pkg.dependencies['less-middleware'] = '*'; + break; + default: + if (program.css) { + pkg.dependencies[program.css] = '*'; + } + } + + write(path + '/package.json', JSON.stringify(pkg, null, 2)); + write(path + '/app.js', app); + }); +} + +/** + * Check if the given directory `path` is empty. + * + * @param {String} path + * @param {Function} fn + */ + +function emptyDirectory(path, fn) { + fs.readdir(path, function(err, files){ + if (err && 'ENOENT' != err.code) throw err; + fn(!files || !files.length); + }); +} + +/** + * echo str > path. + * + * @param {String} path + * @param {String} str + */ + +function write(path, str) { + fs.writeFile(path, str); + console.log(' \x1b[36mcreate\x1b[0m : ' + path); +} + +/** + * Mkdir -p. + * + * @param {String} path + * @param {Function} fn + */ + +function mkdir(path, fn) { + mkdirp(path, 0755, function(err){ + if (err) throw err; + console.log(' \033[36mcreate\033[0m : ' + path); + fn && fn(); + }); +} + +/** + * Exit with the given `str`. + * + * @param {String} str + */ + +function abort(str) { + console.error(str); + process.exit(1); +} diff --git a/node_modules/express/client.js b/node_modules/express/client.js new file mode 100644 index 0000000..8984c44 --- /dev/null +++ b/node_modules/express/client.js @@ -0,0 +1,25 @@ + +var http = require('http'); + +var times = 50; + +while (times--) { + var req = http.request({ + port: 3000 + , method: 'POST' + , headers: { 'Content-Type': 'application/x-www-form-urlencoded' } + }); + + req.on('response', function(res){ + console.log(res.statusCode); + }); + + var n = 500000; + while (n--) { + req.write('foo=bar&bar=baz&'); + } + + req.write('foo=bar&bar=baz'); + + req.end(); +} \ No newline at end of file diff --git a/node_modules/express/index.js b/node_modules/express/index.js new file mode 100644 index 0000000..bfe9934 --- /dev/null +++ b/node_modules/express/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.EXPRESS_COV + ? require('./lib-cov/express') + : require('./lib/express'); \ No newline at end of file diff --git a/node_modules/express/lib/application.js b/node_modules/express/lib/application.js new file mode 100644 index 0000000..7ebc6f6 --- /dev/null +++ b/node_modules/express/lib/application.js @@ -0,0 +1,534 @@ +/** + * Module dependencies. + */ + +var connect = require('connect') + , Router = require('./router') + , methods = require('methods') + , middleware = require('./middleware') + , debug = require('debug')('express:application') + , locals = require('./utils').locals + , View = require('./view') + , utils = connect.utils + , path = require('path') + , http = require('http') + , join = path.join; + +/** + * Application prototype. + */ + +var app = exports = module.exports = {}; + +/** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + * + * @api private + */ + +app.init = function(){ + this.cache = {}; + this.settings = {}; + this.engines = {}; + this.viewCallbacks = []; + this.defaultConfiguration(); +}; + +/** + * Initialize application configuration. + * + * @api private + */ + +app.defaultConfiguration = function(){ + // default settings + this.enable('x-powered-by'); + this.set('env', process.env.NODE_ENV || 'development'); + this.set('subdomain offset', 2); + debug('booting in %s mode', this.get('env')); + + // implicit middleware + this.use(connect.query()); + this.use(middleware.init(this)); + + // inherit protos + this.on('mount', function(parent){ + this.request.__proto__ = parent.request; + this.response.__proto__ = parent.response; + this.engines.__proto__ = parent.engines; + }); + + // router + this._router = new Router(this); + this.routes = this._router.map; + this.__defineGetter__('router', function(){ + this._usedRouter = true; + this._router.caseSensitive = this.enabled('case sensitive routing'); + this._router.strict = this.enabled('strict routing'); + return this._router.middleware; + }); + + // setup locals + this.locals = locals(this); + + // default locals + this.locals.settings = this.settings; + + // default configuration + this.set('views', process.cwd() + '/views'); + this.set('jsonp callback name', 'callback'); + + this.configure('development', function(){ + this.set('json spaces', 2); + }); + + this.configure('production', function(){ + this.enable('view cache'); + }); +}; + +/** + * Proxy `connect#use()` to apply settings to + * mounted applications. + * + * @param {String|Function|Server} route + * @param {Function|Server} fn + * @return {app} for chaining + * @api public + */ + +app.use = function(route, fn){ + var app; + + // default route to '/' + if ('string' != typeof route) fn = route, route = '/'; + + // express app + if (fn.handle && fn.set) app = fn; + + // restore .app property on req and res + if (app) { + app.route = route; + fn = function(req, res, next) { + var orig = req.app; + app.handle(req, res, function(err){ + req.app = res.app = orig; + req.__proto__ = orig.request; + res.__proto__ = orig.response; + next(err); + }); + }; + } + + connect.proto.use.call(this, route, fn); + + // mounted an app + if (app) { + app.parent = this; + app.emit('mount', this); + } + + return this; +}; + +/** + * Register the given template engine callback `fn` + * as `ext`. + * + * By default will `require()` the engine based on the + * file extension. For example if you try to render + * a "foo.jade" file Express will invoke the following internally: + * + * app.engine('jade', require('jade').__express); + * + * For engines that do not provide `.__express` out of the box, + * or if you wish to "map" a different extension to the template engine + * you may use this method. For example mapping the EJS template engine to + * ".html" files: + * + * app.engine('html', require('ejs').renderFile); + * + * In this case EJS provides a `.renderFile()` method with + * the same signature that Express expects: `(path, options, callback)`, + * though note that it aliases this method as `ejs.__express` internally + * so if you're using ".ejs" extensions you dont need to do anything. + * + * Some template engines do not follow this convention, the + * [Consolidate.js](https://github.com/visionmedia/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seeessly within Express. + * + * @param {String} ext + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.engine = function(ext, fn){ + if ('function' != typeof fn) throw new Error('callback function required'); + if ('.' != ext[0]) ext = '.' + ext; + this.engines[ext] = fn; + return this; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback(s). + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the samesignature as middleware, the only differencing + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * next(err); + * } else if (user) { + * req.user = user; + * next(); + * } else { + * next(new Error('failed to load user')); + * } + * }); + * }); + * + * @param {String|Array} name + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.param = function(name, fn){ + var self = this + , fns = [].slice.call(arguments, 1); + + // array + if (Array.isArray(name)) { + name.forEach(function(name){ + fns.forEach(function(fn){ + self.param(name, fn); + }); + }); + // param logic + } else if ('function' == typeof name) { + this._router.param(name); + // single + } else { + if (':' == name[0]) name = name.substr(1); + fns.forEach(function(fn){ + self._router.param(name, fn); + }); + } + + return this; +}; + +/** + * Assign `setting` to `val`, or return `setting`'s value. + * + * app.set('foo', 'bar'); + * app.get('foo'); + * // => "bar" + * + * Mounted servers inherit their parent server's settings. + * + * @param {String} setting + * @param {String} val + * @return {Server} for chaining + * @api public + */ + +app.set = function(setting, val){ + if (1 == arguments.length) { + if (this.settings.hasOwnProperty(setting)) { + return this.settings[setting]; + } else if (this.parent) { + return this.parent.set(setting); + } + } else { + this.settings[setting] = val; + return this; + } +}; + +/** + * Return the app's absolute pathname + * based on the parent(s) that have + * mounted it. + * + * For example if the application was + * mounted as "/admin", which itself + * was mounted as "/blog" then the + * return value would be "/blog/admin". + * + * @return {String} + * @api private + */ + +app.path = function(){ + return this.parent + ? this.parent.path() + this.route + : ''; +}; + +/** + * Check if `setting` is enabled (truthy). + * + * app.enabled('foo') + * // => false + * + * app.enable('foo') + * app.enabled('foo') + * // => true + * + * @param {String} setting + * @return {Boolean} + * @api public + */ + +app.enabled = function(setting){ + return !!this.set(setting); +}; + +/** + * Check if `setting` is disabled. + * + * app.disabled('foo') + * // => true + * + * app.enable('foo') + * app.disabled('foo') + * // => false + * + * @param {String} setting + * @return {Boolean} + * @api public + */ + +app.disabled = function(setting){ + return !this.set(setting); +}; + +/** + * Enable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @api public + */ + +app.enable = function(setting){ + return this.set(setting, true); +}; + +/** + * Disable `setting`. + * + * @param {String} setting + * @return {app} for chaining + * @api public + */ + +app.disable = function(setting){ + return this.set(setting, false); +}; + +/** + * Configure callback for zero or more envs, + * when no `env` is specified that callback will + * be invoked for all environments. Any combination + * can be used multiple times, in any order desired. + * + * Examples: + * + * app.configure(function(){ + * // executed for all envs + * }); + * + * app.configure('stage', function(){ + * // executed staging env + * }); + * + * app.configure('stage', 'production', function(){ + * // executed for stage and production + * }); + * + * Note: + * + * These callbacks are invoked immediately, and + * are effectively sugar for the following: + * + * var env = process.env.NODE_ENV || 'development'; + * + * switch (env) { + * case 'development': + * ... + * break; + * case 'stage': + * ... + * break; + * case 'production': + * ... + * break; + * } + * + * @param {String} env... + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.configure = function(env, fn){ + var envs = 'all' + , args = [].slice.call(arguments); + fn = args.pop(); + if (args.length) envs = args; + if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this); + return this; +}; + +/** + * Delegate `.VERB(...)` calls to `router.VERB(...)`. + */ + +methods.forEach(function(method){ + app[method] = function(path){ + if ('get' == method && 1 == arguments.length) return this.set(path); + + // if no router attacked yet, attach the router + if (!this._usedRouter) this.use(this.router); + + // setup route + this._router[method].apply(this._router, arguments); + return this; + }; +}); + +/** + * Special-cased "all" method, applying the given route `path`, + * middleware, and callback to _every_ HTTP method. + * + * @param {String} path + * @param {Function} ... + * @return {app} for chaining + * @api public + */ + +app.all = function(path){ + var args = arguments; + methods.forEach(function(method){ + app[method].apply(this, args); + }, this); + return this; +}; + +// del -> delete alias + +app.del = app.delete; + +/** + * Render the given view `name` name with `options` + * and a callback accepting an error and the + * rendered template string. + * + * Example: + * + * app.render('email', { name: 'Tobi' }, function(err, html){ + * // ... + * }) + * + * @param {String} name + * @param {String|Function} options or fn + * @param {Function} fn + * @api public + */ + +app.render = function(name, options, fn){ + var opts = {} + , cache = this.cache + , engines = this.engines + , view; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge app.locals + utils.merge(opts, this.locals); + + // merge options._locals + if (options._locals) utils.merge(opts, options._locals); + + // merge options + utils.merge(opts, options); + + // set .cache unless explicitly provided + opts.cache = null == opts.cache + ? this.enabled('view cache') + : opts.cache; + + // primed cache + if (opts.cache) view = cache[name]; + + // view + if (!view) { + view = new View(name, { + defaultEngine: this.get('view engine'), + root: this.get('views'), + engines: engines + }); + + if (!view.path) { + var err = new Error('Failed to lookup view "' + name + '"'); + err.view = view; + return fn(err); + } + + // prime the cache + if (opts.cache) cache[name] = view; + } + + // render + try { + view.render(opts, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Listen for connections. + * + * A node `http.Server` is returned, with this + * application (which is a `Function`) as its + * callback. If you wish to create both an HTTP + * and HTTPS server you may do so with the "http" + * and "https" modules as shown here: + * + * var http = require('http') + * , https = require('https') + * , express = require('express') + * , app = express(); + * + * http.createServer(app).listen(80); + * https.createServer({ ... }, app).listen(443); + * + * @return {http.Server} + * @api public + */ + +app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; diff --git a/node_modules/express/lib/express.js b/node_modules/express/lib/express.js new file mode 100644 index 0000000..2a704b2 --- /dev/null +++ b/node_modules/express/lib/express.js @@ -0,0 +1,92 @@ +/** + * Module dependencies. + */ + +var connect = require('connect') + , proto = require('./application') + , Route = require('./router/route') + , Router = require('./router') + , req = require('./request') + , res = require('./response') + , utils = connect.utils; + +/** + * Expose `createApplication()`. + */ + +exports = module.exports = createApplication; + +/** + * Framework version. + */ + +exports.version = '3.1.0'; + +/** + * Expose mime. + */ + +exports.mime = connect.mime; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + +function createApplication() { + var app = connect(); + utils.merge(app, proto); + app.request = { __proto__: req }; + app.response = { __proto__: res }; + app.init(); + return app; +} + +/** + * Expose connect.middleware as express.* + * for example `express.logger` etc. + */ + +for (var key in connect.middleware) { + Object.defineProperty( + exports + , key + , Object.getOwnPropertyDescriptor(connect.middleware, key)); +} + +/** + * Error on createServer(). + */ + +exports.createServer = function(){ + console.warn('Warning: express.createServer() is deprecated, express'); + console.warn('applications no longer inherit from http.Server,'); + console.warn('please use:'); + console.warn(''); + console.warn(' var express = require("express");'); + console.warn(' var app = express();'); + console.warn(''); + return createApplication(); +}; + +/** + * Expose the prototypes. + */ + +exports.application = proto; +exports.request = req; +exports.response = res; + +/** + * Expose constructors. + */ + +exports.Route = Route; +exports.Router = Router; + +// Error handler title + +exports.errorHandler.title = 'Express'; + diff --git a/node_modules/express/lib/middleware.js b/node_modules/express/lib/middleware.js new file mode 100644 index 0000000..308c5bb --- /dev/null +++ b/node_modules/express/lib/middleware.js @@ -0,0 +1,33 @@ + +/** + * Module dependencies. + */ + +var utils = require('./utils'); + +/** + * Initialization middleware, exposing the + * request and response to eachother, as well + * as defaulting the X-Powered-By header field. + * + * @param {Function} app + * @return {Function} + * @api private + */ + +exports.init = function(app){ + return function expressInit(req, res, next){ + req.app = res.app = app; + if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); + req.res = res; + res.req = req; + req.next = next; + + req.__proto__ = app.request; + res.__proto__ = app.response; + + res.locals = res.locals || utils.locals(res); + + next(); + } +}; diff --git a/node_modules/express/lib/request.js b/node_modules/express/lib/request.js new file mode 100644 index 0000000..1c6048d --- /dev/null +++ b/node_modules/express/lib/request.js @@ -0,0 +1,493 @@ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('./utils') + , connect = require('connect') + , fresh = require('fresh') + , parseRange = require('range-parser') + , parse = connect.utils.parseUrl + , mime = connect.mime; + +/** + * Request prototype. + */ + +var req = exports = module.exports = { + __proto__: http.IncomingMessage.prototype +}; + +/** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param {String} name + * @return {String} + * @api public + */ + +req.get = +req.header = function(name){ + switch (name = name.toLowerCase()) { + case 'referer': + case 'referrer': + return this.headers.referrer + || this.headers.referer; + default: + return this.headers[name]; + } +}; + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json", a comma-delimted list such as "json, html, text/plain", + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html, json'); + * // => "json" + * + * @param {String|Array} type(s) + * @return {String} + * @api public + */ + +req.accepts = function(type){ + return utils.accepts(type, this.get('Accept')); +}; + +/** + * Check if the given `charset` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} charset + * @return {Boolean} + * @api public + */ + +req.acceptsCharset = function(charset){ + var accepted = this.acceptedCharsets; + return accepted.length + ? ~accepted.indexOf(charset) + : true; +}; + +/** + * Check if the given `lang` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} lang + * @return {Boolean} + * @api public + */ + +req.acceptsLanguage = function(lang){ + var accepted = this.acceptedLanguages; + return accepted.length + ? ~accepted.indexOf(lang) + : true; +}; + +/** + * Parse Range header field, + * capping to the given `size`. + * + * Unspecified ranges such as "0-" require + * knowledge of your resource length. In + * the case of a byte range this is of course + * the total number of bytes. If the Range + * header field is not given `null` is returned, + * `-1` when unsatisfiable, `-2` when syntactically invalid. + * + * NOTE: remember that ranges are inclusive, so + * for example "Range: users=0-3" should respond + * with 4 users when available, not 3. + * + * @param {Number} size + * @return {Array} + * @api public + */ + +req.range = function(size){ + var range = this.get('Range'); + if (!range) return; + return parseRange(size, range); +}; + +/** + * Return an array of Accepted media types + * ordered from highest quality to lowest. + * + * Examples: + * + * [ { value: 'application/json', + * quality: 1, + * type: 'application', + * subtype: 'json' }, + * { value: 'text/html', + * quality: 0.5, + * type: 'text', + * subtype: 'html' } ] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('accepted', function(){ + var accept = this.get('Accept'); + return accept + ? utils.parseAccept(accept) + : []; +}); + +/** + * Return an array of Accepted languages + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Language: en;q=.5, en-us + * ['en-us', 'en'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedLanguages', function(){ + var accept = this.get('Accept-Language'); + return accept + ? utils + .parseQuality(accept) + .map(function(obj){ + return obj.value; + }) + : []; +}); + +/** + * Return an array of Accepted charsets + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8 + * ['unicode-1-1', 'iso-8859-5'] + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('acceptedCharsets', function(){ + var accept = this.get('Accept-Charset'); + return accept + ? utils + .parseQuality(accept) + .map(function(obj){ + return obj.value; + }) + : []; +}); + +/** + * Return the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `connect.bodyParser()` middleware. + * + * @param {String} name + * @param {Mixed} defaultValue + * @return {String} + * @api public + */ + +req.param = function(name, defaultValue){ + var params = this.params || {}; + var body = this.body || {}; + var query = this.query || {}; + if (null != params[name] && params.hasOwnProperty(name)) return params[name]; + if (null != body[name]) return body[name]; + if (null != query[name]) return query[name]; + return defaultValue; +}; + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param {String} type + * @return {Boolean} + * @api public + */ + +req.is = function(type){ + var ct = this.get('Content-Type'); + if (!ct) return false; + ct = ct.split(';')[0]; + if (!~type.indexOf('/')) type = mime.lookup(type); + if (~type.indexOf('*')) { + type = type.split('/'); + ct = ct.split('/'); + if ('*' == type[0] && type[1] == ct[1]) return true; + if ('*' == type[1] && type[0] == ct[0]) return true; + return false; + } + return !! ~ct.indexOf(type); +}; + +/** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting is enabled the "X-Forwarded-Proto" header + * field will be trusted. If you're running behind + * a reverse proxy that supplies https for you this + * may be enabled. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('protocol', function(){ + var trustProxy = this.app.get('trust proxy'); + return this.connection.encrypted + ? 'https' + : trustProxy + ? (this.get('X-Forwarded-Proto') || 'http') + : 'http'; +}); + +/** + * Short-hand for: + * + * req.protocol == 'https' + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('secure', function(){ + return 'https' == this.protocol; +}); + +/** + * Return the remote address, or when + * "trust proxy" is `true` return + * the upstream addr. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('ip', function(){ + return this.ips[0] || this.connection.remoteAddress; +}); + +/** + * When "trust proxy" is `true`, parse + * the "X-Forwarded-For" ip address list. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream. + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('ips', function(){ + var trustProxy = this.app.get('trust proxy'); + var val = this.get('X-Forwarded-For'); + return trustProxy && val + ? val.split(/ *, */) + : []; +}); + +/** + * Return basic auth credentials. + * + * Examples: + * + * // http://tobi:hello@example.com + * req.auth + * // => { username: 'tobi', password: 'hello' } + * + * @return {Object} or undefined + * @api public + */ + +req.__defineGetter__('auth', function(){ + // missing + var auth = this.get('Authorization'); + if (!auth) return; + + // malformed + var parts = auth.split(' '); + if ('basic' != parts[0].toLowerCase()) return; + if (!parts[1]) return; + auth = parts[1]; + + // credentials + auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/); + if (!auth) return; + return { username: auth[1], password: auth[2] }; +}); + +/** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + * + * @return {Array} + * @api public + */ + +req.__defineGetter__('subdomains', function(){ + var offset = this.app.get('subdomain offset'); + return this.get('Host') + .split('.') + .reverse() + .slice(offset); +}); + +/** + * Short-hand for `url.parse(req.url).pathname`. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('path', function(){ + return parse(this).pathname; +}); + +/** + * Parse the "Host" header field hostname. + * + * @return {String} + * @api public + */ + +req.__defineGetter__('host', function(){ + return this.get('Host').split(':')[0]; +}); + +/** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('fresh', function(){ + var method = this.method; + var s = this.res.statusCode; + + // GET or HEAD for weak freshness validation only + if ('GET' != method && 'HEAD' != method) return false; + + // 2xx or 304 as per rfc2616 14.26 + if ((s >= 200 && s < 300) || 304 == s) { + return fresh(this.headers, this.res._headers); + } + + return false; +}); + +/** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('stale', function(){ + return !this.fresh; +}); + +/** + * Check if the request was an _XMLHttpRequest_. + * + * @return {Boolean} + * @api public + */ + +req.__defineGetter__('xhr', function(){ + var val = this.get('X-Requested-With') || ''; + return 'xmlhttprequest' == val.toLowerCase(); +}); diff --git a/node_modules/express/lib/response.js b/node_modules/express/lib/response.js new file mode 100644 index 0000000..2b66c88 --- /dev/null +++ b/node_modules/express/lib/response.js @@ -0,0 +1,754 @@ +/** + * Module dependencies. + */ + +var http = require('http') + , path = require('path') + , connect = require('connect') + , utils = connect.utils + , sign = require('cookie-signature').sign + , normalizeType = require('./utils').normalizeType + , normalizeTypes = require('./utils').normalizeTypes + , etag = require('./utils').etag + , statusCodes = http.STATUS_CODES + , cookie = require('cookie') + , send = require('send') + , mime = connect.mime + , basename = path.basename + , extname = path.extname + , join = path.join; + +/** + * Response prototype. + */ + +var res = module.exports = { + __proto__: http.ServerResponse.prototype +}; + +/** + * Set status `code`. + * + * @param {Number} code + * @return {ServerResponse} + * @api public + */ + +res.status = function(code){ + this.statusCode = code; + return this; +}; + +/** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param {Object} links + * @return {ServerResponse} + * @api public + */ + +res.links = function(links){ + return this.set('Link', Object.keys(links).map(function(rel){ + return '<' + links[rel] + '>; rel="' + rel + '"'; + }).join(', ')); +}; + +/** + * Send a response. + * + * Examples: + * + * res.send(new Buffer('wahoo')); + * res.send({ some: 'json' }); + * res.send('

some html

'); + * res.send(404, 'Sorry, cant find that'); + * res.send(404); + * + * @param {Mixed} body or status + * @param {Mixed} body + * @return {ServerResponse} + * @api public + */ + +res.send = function(body){ + var req = this.req + , head = 'HEAD' == req.method + , len; + + // allow status / body + if (2 == arguments.length) { + // res.send(body, status) backwards compat + if ('number' != typeof body && 'number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = body; + body = arguments[1]; + } + } + + switch (typeof body) { + // response status + case 'number': + this.get('Content-Type') || this.type('txt'); + this.statusCode = body; + body = http.STATUS_CODES[body]; + break; + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.charset = this.charset || 'utf-8'; + this.type('html'); + } + break; + case 'boolean': + case 'object': + if (null == body) { + body = ''; + } else if (Buffer.isBuffer(body)) { + this.get('Content-Type') || this.type('bin'); + } else { + return this.json(body); + } + break; + } + + // populate Content-Length + if (undefined !== body && !this.get('Content-Length')) { + this.set('Content-Length', len = Buffer.isBuffer(body) + ? body.length + : Buffer.byteLength(body)); + } + + // ETag support + // TODO: W/ support + if (len > 1024) { + if (!this.get('ETag')) { + this.set('ETag', etag(body)); + } + } + + // freshness + if (req.fresh) this.statusCode = 304; + + // strip irrelevant headers + if (204 == this.statusCode || 304 == this.statusCode) { + this.removeHeader('Content-Type'); + this.removeHeader('Content-Length'); + this.removeHeader('Transfer-Encoding'); + body = ''; + } + + // respond + this.end(head ? null : body); + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * res.json(500, 'oh noes!'); + * res.json(404, 'I dont have that'); + * + * @param {Mixed} obj or status + * @param {Mixed} obj + * @return {ServerResponse} + * @api public + */ + +res.json = function(obj){ + // allow status / body + if (2 == arguments.length) { + // res.json(body, status) backwards compat + if ('number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = obj; + obj = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(obj, replacer, spaces); + + // content-type + this.charset = this.charset || 'utf-8'; + this.get('Content-Type') || this.set('Content-Type', 'application/json'); + + return this.send(body); +}; + +/** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * res.jsonp(500, 'oh noes!'); + * res.jsonp(404, 'I dont have that'); + * + * @param {Mixed} obj or status + * @param {Mixed} obj + * @return {ServerResponse} + * @api public + */ + +res.jsonp = function(obj){ + // allow status / body + if (2 == arguments.length) { + // res.json(body, status) backwards compat + if ('number' == typeof arguments[1]) { + this.statusCode = arguments[1]; + } else { + this.statusCode = obj; + obj = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(obj, replacer, spaces) + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + this.charset = this.charset || 'utf-8'; + this.set('Content-Type', 'application/json'); + + // jsonp + if (callback) { + this.set('Content-Type', 'text/javascript'); + var cb = callback.replace(/[^\[\]\w$.]/g, ''); + body = cb + ' && ' + cb + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `fn(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 + * - `root` root directory for relative filenames + * + * Examples: + * + * The following example illustrates how `res.sendfile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendfile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendfile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @param {String} path + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +res.sendfile = function(path, options, fn){ + var self = this + , req = self.req + , next = this.req.next + , options = options || {} + , done; + + // support function as second arg + if ('function' == typeof options) { + fn = options; + options = {}; + } + + // socket errors + req.socket.on('error', error); + + // errors + function error(err) { + if (done) return; + done = true; + + // clean up + cleanup(); + if (!self.headerSent) self.removeHeader('Content-Disposition'); + + // callback available + if (fn) return fn(err); + + // list in limbo if there's no callback + if (self.headerSent) return; + + // delegate + next(err); + } + + // streaming + function stream() { + if (done) return; + cleanup(); + if (fn) self.on('finish', fn); + } + + // cleanup + function cleanup() { + req.socket.removeListener('error', error); + } + + // transfer + var file = send(req, path); + if (options.root) file.root(options.root); + file.maxage(options.maxAge || 0); + file.on('error', error); + file.on('directory', next); + file.on('stream', stream); + file.pipe(this); + this.on('finish', cleanup); +}; + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `fn(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headerSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + * + * @param {String} path + * @param {String|Function} filename or fn + * @param {Function} fn + * @api public + */ + +res.download = function(path, filename, fn){ + // support function as second arg + if ('function' == typeof filename) { + fn = filename; + filename = null; + } + + filename = filename || path; + this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"'); + return this.sendfile(path, fn); +}; + +/** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param {String} type + * @return {ServerResponse} for chaining + * @api public + */ + +res.contentType = +res.type = function(type){ + return this.set('Content-Type', ~type.indexOf('/') + ? type + : mime.lookup(type)); +}; + +/** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('

hey

'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('

hey

'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param {Object} obj + * @return {ServerResponse} for chaining + * @api public + */ + +res.format = function(obj){ + var req = this.req + , next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = req.accepts(keys); + + this.set('Vary', 'Accept'); + + if (key) { + this.set('Content-Type', normalizeType(key)); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = 406; + err.types = normalizeTypes(keys); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @api public + */ + +res.attachment = function(filename){ + if (filename) this.type(extname(filename)); + this.set('Content-Disposition', filename + ? 'attachment; filename="' + basename(filename) + '"' + : 'attachment'); + return this; +}; + +/** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + * + * @param {String|Object|Array} field + * @param {String} val + * @return {ServerResponse} for chaining + * @api public + */ + +res.set = +res.header = function(field, val){ + if (2 == arguments.length) { + if (Array.isArray(val)) val = val.map(String); + else val = String(val); + this.setHeader(field, val); + } else { + for (var key in field) { + this.set(key, field[key]); + } + } + return this; +}; + +/** + * Get value for header `field`. + * + * @param {String} field + * @return {String} + * @api public + */ + +res.get = function(field){ + return this.getHeader(field); +}; + +/** + * Clear cookie `name`. + * + * @param {String} name + * @param {Object} options + * @param {ServerResponse} for chaining + * @api public + */ + +res.clearCookie = function(name, options){ + var opts = { expires: new Date(1), path: '/' }; + return this.cookie(name, '', options + ? utils.merge(opts, options) + : opts); +}; + +/** + * Set cookie `name` to `val`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + * + * @param {String} name + * @param {String|Object} val + * @param {Options} options + * @api public + */ + +res.cookie = function(name, val, options){ + options = utils.merge({}, options); + var secret = this.req.secret; + var signed = options.signed; + if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies'); + if ('object' == typeof val) val = 'j:' + JSON.stringify(val); + if (signed) val = 's:' + sign(val, secret); + if ('maxAge' in options) { + options.expires = new Date(Date.now() + options.maxAge); + options.maxAge /= 1000; + } + if (null == options.path) options.path = '/'; + this.set('Set-Cookie', cookie.serialize(name, String(val), options)); + return this; +}; + + +/** + * Set the location header to `url`. + * + * The given `url` can also be the name of a mapped url, for + * example by default express supports "back" which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com'); + * res.location('../login'); // /blog/post/1 -> /blog/login + * + * Mounting: + * + * When an application is mounted and `res.location()` + * is given a path that does _not_ lead with "/" it becomes + * relative to the mount-point. For example if the application + * is mounted at "/blog", the following would become "/blog/login". + * + * res.location('login'); + * + * While the leading slash would result in a location of "/login": + * + * res.location('/login'); + * + * @param {String} url + * @api public + */ + +res.location = function(url){ + var app = this.app + , req = this.req; + + // setup redirect map + var map = { back: req.get('Referrer') || '/' }; + + // perform redirect + url = map[url] || url; + + // relative + if (!~url.indexOf('://') && 0 != url.indexOf('//')) { + var path = app.path(); + + // relative to path + if ('.' == url[0]) { + url = req.path + '/' + url; + // relative to mount-point + } else if ('/' != url[0]) { + url = path + '/' + url; + } + } + + // Respond + this.set('Location', url); + return this; +}; + +/** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com'); + * res.redirect(301, 'http://example.com'); + * res.redirect('http://example.com', 301); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + * + * @param {String} url + * @param {Number} code + * @api public + */ + +res.redirect = function(url){ + var app = this.app + , head = 'HEAD' == this.req.method + , status = 302 + , body; + + // allow status / url + if (2 == arguments.length) { + if ('number' == typeof url) { + status = url; + url = arguments[1]; + } else { + status = arguments[1]; + } + } + + // Set location header + this.location(url); + url = this.get('Location'); + + // Support text/{plain,html} by default + this.format({ + text: function(){ + body = statusCodes[status] + '. Redirecting to ' + encodeURI(url); + }, + + html: function(){ + var u = utils.escape(url); + body = '

' + statusCodes[status] + '. Redirecting to ' + u + '

'; + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + this.end(head ? null : body); +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @param {String} view + * @param {Object|Function} options or callback function + * @param {Function} fn + * @api public + */ + +res.render = function(view, options, fn){ + var self = this + , options = options || {} + , req = this.req + , app = req.app; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge res.locals + options._locals = self.locals; + + // default callback to respond + fn = fn || function(err, str){ + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, options, fn); +}; diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..662dc29 --- /dev/null +++ b/node_modules/express/lib/router/index.js @@ -0,0 +1,273 @@ +/** + * Module dependencies. + */ + +var Route = require('./route') + , utils = require('../utils') + , methods = require('methods') + , debug = require('debug')('express:router') + , parse = require('connect').utils.parseUrl; + +/** + * Expose `Router` constructor. + */ + +exports = module.exports = Router; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @api private + */ + +function Router(options) { + options = options || {}; + var self = this; + this.map = {}; + this.params = {}; + this._params = []; + this.caseSensitive = options.caseSensitive; + this.strict = options.strict; + this.middleware = function router(req, res, next){ + self._dispatch(req, res, next); + }; +} + +/** + * Register a param callback `fn` for the given `name`. + * + * @param {String|Function} name + * @param {Function} fn + * @return {Router} for chaining + * @api public + */ + +Router.prototype.param = function(name, fn){ + // param logic + if ('function' == typeof name) { + this._params.push(name); + return; + } + + // apply param functions + var params = this._params + , len = params.length + , ret; + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' != typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Route dispatcher aka the route "middleware". + * + * @param {IncomingMessage} req + * @param {ServerResponse} res + * @param {Function} next + * @api private + */ + +Router.prototype._dispatch = function(req, res, next){ + var params = this.params + , self = this; + + debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl); + + // route dispatch + (function pass(i, err){ + var paramCallbacks + , paramIndex = 0 + , paramVal + , route + , keys + , key; + + // match next route + function nextRoute(err) { + pass(req._route_index + 1, err); + } + + // match route + req.route = route = self.matchRequest(req, i); + + // no route + if (!route) return next(err); + debug('matched %s %s', route.method, route.path); + + // we have a route + // start at param 0 + req.params = route.params; + keys = route.keys; + i = 0; + + // param callbacks + function param(err) { + paramIndex = 0; + key = keys[i++]; + paramVal = key && req.params[key.name]; + paramCallbacks = key && params[key.name]; + + try { + if ('route' == err) { + nextRoute(); + } else if (err) { + i = 0; + callbacks(err); + } else if (paramCallbacks && undefined !== paramVal) { + paramCallback(); + } else if (key) { + param(); + } else { + i = 0; + callbacks(); + } + } catch (err) { + param(err); + } + }; + + param(err); + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + if (err || !fn) return param(err); + fn(req, res, paramCallback, paramVal, key.name); + } + + // invoke route callbacks + function callbacks(err) { + var fn = route.callbacks[i++]; + try { + if ('route' == err) { + nextRoute(); + } else if (err && fn) { + if (fn.length < 4) return callbacks(err); + fn(err, req, res, callbacks); + } else if (fn) { + if (fn.length < 4) return fn(req, res, callbacks); + callbacks(); + } else { + nextRoute(err); + } + } catch (err) { + callbacks(err); + } + } + })(0); +}; + +/** + * Attempt to match a route for `req` + * with optional starting index of `i` + * defaulting to 0. + * + * @param {IncomingMessage} req + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.matchRequest = function(req, i, head){ + var method = req.method.toLowerCase() + , url = parse(req) + , path = url.pathname + , routes = this.map + , i = i || 0 + , route; + + // HEAD support + if (!head && 'head' == method) { + route = this.matchRequest(req, i, true); + if (route) return route; + method = 'get'; + } + + // routes for this method + if (routes = routes[method]) { + + // matching routes + for (var len = routes.length; i < len; ++i) { + route = routes[i]; + if (route.match(path)) { + req._route_index = i; + return route; + } + } + } +}; + +/** + * Attempt to match a route for `method` + * and `url` with optional starting + * index of `i` defaulting to 0. + * + * @param {String} method + * @param {String} url + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.match = function(method, url, i, head){ + var req = { method: method, url: url }; + return this.matchRequest(req, i, head); +}; + +/** + * Route `method`, `path`, and one or more callbacks. + * + * @param {String} method + * @param {String} path + * @param {Function} callback... + * @return {Router} for chaining + * @api private + */ + +Router.prototype.route = function(method, path, callbacks){ + var method = method.toLowerCase() + , callbacks = utils.flatten([].slice.call(arguments, 2)); + + // ensure path was given + if (!path) throw new Error('Router#' + method + '() requires a path'); + + // ensure all callbacks are functions + callbacks.forEach(function(fn, i){ + if ('function' == typeof fn) return; + var type = {}.toString.call(fn); + var msg = '.' + method + '() requires callback functions but got a ' + type; + throw new Error(msg); + }); + + // create the route + debug('defined %s %s', method, path); + var route = new Route(method, path, callbacks, { + sensitive: this.caseSensitive, + strict: this.strict + }); + + // add it + (this.map[method] = this.map[method] || []).push(route); + return this; +}; + +methods.forEach(function(method){ + Router.prototype[method] = function(path){ + var args = [method].concat([].slice.call(arguments)); + this.route.apply(this, args); + return this; + }; +}); diff --git a/node_modules/express/lib/router/route.js b/node_modules/express/lib/router/route.js new file mode 100644 index 0000000..c1a0b5e --- /dev/null +++ b/node_modules/express/lib/router/route.js @@ -0,0 +1,72 @@ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Expose `Route`. + */ + +module.exports = Route; + +/** + * Initialize `Route` with the given HTTP `method`, `path`, + * and an array of `callbacks` and `options`. + * + * Options: + * + * - `sensitive` enable case-sensitive routes + * - `strict` enable strict matching for trailing slashes + * + * @param {String} method + * @param {String} path + * @param {Array} callbacks + * @param {Object} options. + * @api private + */ + +function Route(method, path, callbacks, options) { + options = options || {}; + this.path = path; + this.method = method; + this.callbacks = callbacks; + this.regexp = utils.pathRegexp(path + , this.keys = [] + , options.sensitive + , options.strict); +} + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Route.prototype.match = function(path){ + var keys = this.keys + , params = this.params = [] + , m = this.regexp.exec(path); + + if (!m) return false; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = 'string' == typeof m[i] + ? decodeURIComponent(m[i]) + : m[i]; + + if (key) { + params[key.name] = val; + } else { + params.push(val); + } + } + + return true; +}; diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js new file mode 100644 index 0000000..8b1da1a --- /dev/null +++ b/node_modules/express/lib/utils.js @@ -0,0 +1,282 @@ + +/** + * Module dependencies. + */ + +var mime = require('connect').mime + , crc32 = require('buffer-crc32'); + +/** + * Return ETag for `body`. + * + * @param {String|Buffer} body + * @return {String} + * @api private + */ + +exports.etag = function(body){ + return '"' + crc32.signed(body) + '"'; +}; + +/** + * Make `locals()` bound to the given `obj`. + * + * This is used for `app.locals` and `res.locals`. + * + * @param {Object} obj + * @return {Function} + * @api private + */ + +exports.locals = function(obj){ + obj.viewCallbacks = obj.viewCallbacks || []; + + function locals(obj){ + for (var key in obj) locals[key] = obj[key]; + return obj; + }; + + return locals; +}; + +/** + * Check if `path` looks absolute. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +exports.isAbsolute = function(path){ + if ('/' == path[0]) return true; + if (':' == path[1] && '\\' == path[2]) return true; +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = function(arr, ret){ + var ret = ret || [] + , len = arr.length; + for (var i = 0; i < len; ++i) { + if (Array.isArray(arr[i])) { + exports.flatten(arr[i], ret); + } else { + ret.push(arr[i]); + } + } + return ret; +}; + +/** + * Normalize the given `type`, for example "html" becomes "text/html". + * + * @param {String} type + * @return {String} + * @api private + */ + +exports.normalizeType = function(type){ + return ~type.indexOf('/') ? type : mime.lookup(type); +}; + +/** + * Normalize `types`, for example "html" becomes "text/html". + * + * @param {Array} types + * @return {Array} + * @api private + */ + +exports.normalizeTypes = function(types){ + var ret = []; + + for (var i = 0; i < types.length; ++i) { + ret.push(~types[i].indexOf('/') + ? types[i] + : mime.lookup(types[i])); + } + + return ret; +}; + +/** + * Return the acceptable type in `types`, if any. + * + * @param {Array} types + * @param {String} str + * @return {String} + * @api private + */ + +exports.acceptsArray = function(types, str){ + // accept anything when Accept is not present + if (!str) return types[0]; + + // parse + var accepted = exports.parseAccept(str) + , normalized = exports.normalizeTypes(types) + , len = accepted.length; + + for (var i = 0; i < len; ++i) { + for (var j = 0, jlen = types.length; j < jlen; ++j) { + if (exports.accept(normalized[j].split('/'), accepted[i])) { + return types[j]; + } + } + } +}; + +/** + * Check if `type(s)` are acceptable based on + * the given `str`. + * + * @param {String|Array} type(s) + * @param {String} str + * @return {Boolean|String} + * @api private + */ + +exports.accepts = function(type, str){ + if ('string' == typeof type) type = type.split(/ *, */); + return exports.acceptsArray(type, str); +}; + +/** + * Check if `type` array is acceptable for `other`. + * + * @param {Array} type + * @param {Object} other + * @return {Boolean} + * @api private + */ + +exports.accept = function(type, other){ + return (type[0] == other.type || '*' == other.type) + && (type[1] == other.subtype || '*' == other.subtype); +}; + +/** + * Parse accept `str`, returning + * an array objects containing + * `.type` and `.subtype` along + * with the values provided by + * `parseQuality()`. + * + * @param {Type} name + * @return {Type} + * @api private + */ + +exports.parseAccept = function(str){ + return exports + .parseQuality(str) + .map(function(obj){ + var parts = obj.value.split('/'); + obj.type = parts[0]; + obj.subtype = parts[1]; + return obj; + }); +}; + +/** + * Parse quality `str`, returning an + * array of objects with `.value` and + * `.quality`. + * + * @param {Type} name + * @return {Type} + * @api private + */ + +exports.parseQuality = function(str){ + return str + .split(/ *, */) + .map(quality) + .filter(function(obj){ + return obj.quality; + }) + .sort(function(a, b){ + return b.quality - a.quality; + }); +}; + +/** + * Parse quality `str` returning an + * object with `.value` and `.quality`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function quality(str) { + var parts = str.split(/ *; */) + , val = parts[0]; + + var q = parts[1] + ? parseFloat(parts[1].split(/ *= */)[1]) + : 1; + + return { value: val, quality: q }; +} + +/** + * Escape special characters in the given string of html. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +}; + +/** + * Normalize the given path string, + * returning a regular expression. + * + * An empty array should be passed, + * which will contain the placeholder + * key names. For example "/user/:id" will + * then contain ["id"]. + * + * @param {String|RegExp|Array} path + * @param {Array} keys + * @param {Boolean} sensitive + * @param {Boolean} strict + * @return {RegExp} + * @api private + */ + +exports.pathRegexp = function(path, keys, sensitive, strict) { + if (path instanceof RegExp) return path; + if (Array.isArray(path)) path = '(' + path.join('|') + ')'; + path = path + .concat(strict ? '' : '/?') + .replace(/\/\(/g, '(?:/') + .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){ + keys.push({ name: key, optional: !! optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + + (optional || '') + + (star ? '(/*)?' : ''); + }) + .replace(/([\/.])/g, '\\$1') + .replace(/\*/g, '(.*)'); + return new RegExp('^' + path + '$', sensitive ? '' : 'i'); +} \ No newline at end of file diff --git a/node_modules/express/lib/view.js b/node_modules/express/lib/view.js new file mode 100644 index 0000000..c7399a4 --- /dev/null +++ b/node_modules/express/lib/view.js @@ -0,0 +1,76 @@ +/** + * Module dependencies. + */ + +var path = require('path') + , fs = require('fs') + , utils = require('./utils') + , dirname = path.dirname + , basename = path.basename + , extname = path.extname + , exists = fs.existsSync || path.existsSync + , join = path.join; + +/** + * Expose `View`. + */ + +module.exports = View; + +/** + * Initialize a new `View` with the given `name`. + * + * Options: + * + * - `defaultEngine` the default template engine name + * - `engines` template engine require() cache + * - `root` root path for view lookup + * + * @param {String} name + * @param {Object} options + * @api private + */ + +function View(name, options) { + options = options || {}; + this.name = name; + this.root = options.root; + var engines = options.engines; + this.defaultEngine = options.defaultEngine; + var ext = this.ext = extname(name); + if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); + this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); + this.path = this.lookup(name); +} + +/** + * Lookup view by the given `path` + * + * @param {String} path + * @return {String} + * @api private + */ + +View.prototype.lookup = function(path){ + var ext = this.ext; + + // . + if (!utils.isAbsolute(path)) path = join(this.root, path); + if (exists(path)) return path; + + // /index. + path = join(dirname(path), basename(path, ext), 'index' + ext); + if (exists(path)) return path; +}; + +/** + * Render with the given `options` and callback `fn(err, str)`. + * + * @param {Object} options + * @param {Function} fn + * @api private + */ + +View.prototype.render = function(options, fn){ + this.engine(this.path, options, fn); +}; diff --git a/node_modules/express/node_modules/buffer-crc32/.npmignore b/node_modules/express/node_modules/buffer-crc32/.npmignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/node_modules/express/node_modules/buffer-crc32/.travis.yml b/node_modules/express/node_modules/buffer-crc32/.travis.yml new file mode 100644 index 0000000..7a902e8 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - 0.6 + - 0.8 +notifications: + email: + recipients: + - brianloveswords@gmail.com \ No newline at end of file diff --git a/node_modules/express/node_modules/buffer-crc32/README.md b/node_modules/express/node_modules/buffer-crc32/README.md new file mode 100644 index 0000000..4ad5d64 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/README.md @@ -0,0 +1,33 @@ +# buffer-crc32 + +[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32) + +crc32 that works with binary data and fancy character sets, outputs +buffer, signed or unsigned data and has tests. + +Derived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix + +# install +``` +npm install buffer-crc32 +``` + +# example +```js +var crc32 = require('buffer-crc32'); +// works with buffers +var buf = Buffer([[0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00]) +crc32(buf) // -> + +// has convenience methods for getting signed or unsigned ints +crc32.signed(buf) // -> -1805997238 +crc32.unsigned(buf) // -> 2488970058 + +// will cast to buffer if given a string, so you can +// directly use foreign characters safely +crc32('自動販売機') // -> +``` + +# tests +This was tested against the output of zlib's crc32 method. You can run +the tests with`npm test` (requires tap) diff --git a/node_modules/express/node_modules/buffer-crc32/index.js b/node_modules/express/node_modules/buffer-crc32/index.js new file mode 100644 index 0000000..ab0e19e --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/index.js @@ -0,0 +1,84 @@ +var Buffer = require('buffer').Buffer; + +var CRC_TABLE = [ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d +]; + +function bufferizeInt(num) { + var tmp = Buffer(4); + tmp.writeInt32BE(num, 0); + return tmp; +} + +function _crc32(buf) { + if (!Buffer.isBuffer(buf)) + buf = Buffer(buf); + var crc = 0xffffffff; + for (var n = 0; n < buf.length; n++) { + crc = CRC_TABLE[(crc ^ buf[n]) & 0xff] ^ (crc >>> 8); + } + return (crc ^ 0xffffffff); +} + +function crc32() { + return bufferizeInt(_crc32.apply(null, arguments)); +} +crc32.signed = function () { + return _crc32.apply(null, arguments); +}; +crc32.unsigned = function () { + return crc32.apply(null, arguments).readUInt32BE(0); +}; + +module.exports = crc32; diff --git a/node_modules/express/node_modules/buffer-crc32/package.json b/node_modules/express/node_modules/buffer-crc32/package.json new file mode 100644 index 0000000..d9b0b51 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/package.json @@ -0,0 +1,30 @@ +{ + "author": { + "name": "Brian J. Brennan", + "email": "brianloveswords@gmail.com", + "url": "http://bjb.io" + }, + "name": "buffer-crc32", + "description": "A pure javascript CRC32 algorithm that plays nice with binary data", + "version": "0.1.1", + "homepage": "https://github.com/brianloveswords/buffer-crc32", + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/buffer-crc32.git" + }, + "main": "index.js", + "scripts": { + "test": "./node_modules/.bin/tap tests/*.test.js" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.2.5" + }, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "readme": "# buffer-crc32\n\n[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)\n\ncrc32 that works with binary data and fancy character sets, outputs\nbuffer, signed or unsigned data and has tests.\n\nDerived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix\n\n# install\n```\nnpm install buffer-crc32\n```\n\n# example\n```js\nvar crc32 = require('buffer-crc32');\n// works with buffers\nvar buf = Buffer([[0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])\ncrc32(buf) // -> \n\n// has convenience methods for getting signed or unsigned ints\ncrc32.signed(buf) // -> -1805997238\ncrc32.unsigned(buf) // -> 2488970058\n\n// will cast to buffer if given a string, so you can\n// directly use foreign characters safely\ncrc32('自動販売機') // -> \n```\n\n# tests\nThis was tested against the output of zlib's crc32 method. You can run\nthe tests with`npm test` (requires tap)\n", + "_id": "buffer-crc32@0.1.1", + "_from": "buffer-crc32@0.1.1" +} diff --git a/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js b/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js new file mode 100644 index 0000000..d4767e3 --- /dev/null +++ b/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js @@ -0,0 +1,52 @@ +var crc32 = require('..'); +var test = require('tap').test; + +test('simple crc32 is no problem', function (t) { + var input = Buffer('hey sup bros'); + var expected = Buffer([0x47, 0xfa, 0x55, 0x70]); + t.same(crc32(input), expected); + t.end(); +}); + +test('another simple one', function (t) { + var input = Buffer('IEND'); + var expected = Buffer([0xae, 0x42, 0x60, 0x82]); + t.same(crc32(input), expected); + t.end(); +}); + +test('slightly more complex', function (t) { + var input = Buffer([0x00, 0x00, 0x00]); + var expected = Buffer([0xff, 0x41, 0xd9, 0x12]); + t.same(crc32(input), expected); + t.end(); +}); + +test('complex crc32 gets calculated like a champ', function (t) { + var input = Buffer('शीर्षक'); + var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]); + t.same(crc32(input), expected); + t.end(); +}); + +test('casts to buffer if necessary', function (t) { + var input = 'शीर्षक'; + var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]); + t.same(crc32(input), expected); + t.end(); +}); + +test('can do unsigned', function (t) { + var input = 'ham sandwich'; + var expected = -1891873021; + t.same(crc32.signed(input), expected); + t.end(); +}); + +test('can do signed', function (t) { + var input = 'bear sandwich'; + var expected = 3711466352; + t.same(crc32.unsigned(input), expected); + t.end(); +}); + diff --git a/node_modules/express/node_modules/commander/.npmignore b/node_modules/express/node_modules/commander/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/commander/.travis.yml b/node_modules/express/node_modules/commander/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/express/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/express/node_modules/commander/History.md b/node_modules/express/node_modules/commander/History.md new file mode 100644 index 0000000..4961d2e --- /dev/null +++ b/node_modules/express/node_modules/commander/History.md @@ -0,0 +1,107 @@ + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/commander/Makefile b/node_modules/express/node_modules/commander/Makefile new file mode 100644 index 0000000..0074625 --- /dev/null +++ b/node_modules/express/node_modules/commander/Makefile @@ -0,0 +1,7 @@ + +TESTS = $(shell find test/test.*.js) + +test: + @./test/run $(TESTS) + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/commander/Readme.md b/node_modules/express/node_modules/commander/Readme.md new file mode 100644 index 0000000..b8328c3 --- /dev/null +++ b/node_modules/express/node_modules/commander/Readme.md @@ -0,0 +1,262 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## 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. \ No newline at end of file diff --git a/node_modules/express/node_modules/commander/index.js b/node_modules/express/node_modules/commander/index.js new file mode 100644 index 0000000..06ec1e4 --- /dev/null +++ b/node_modules/express/node_modules/commander/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/commander'); \ No newline at end of file diff --git a/node_modules/express/node_modules/commander/lib/commander.js b/node_modules/express/node_modules/commander/lib/commander.js new file mode 100644 index 0000000..5ba87eb --- /dev/null +++ b/node_modules/express/node_modules/commander/lib/commander.js @@ -0,0 +1,1026 @@ + +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , tty = require('tty') + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this.args = []; + this.name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + return cmd; +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self.args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self.args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this.name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + self.args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self.args.length) { + args[self.args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // store raw args + this.rawArgs = argv; + + // guess name + if (!this.name) this.name = basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + this.args = parsed.args; + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0]) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || '-' == arg[0]) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this.args.length ? ' ' + args : ''); + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return cmd.name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args + + (cmd.description() + ? '\n' + cmd.description() + : ''); + }).join('\n\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this.name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + process.stdin.resume(); + tty.setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.removeAllListeners('keypress'); + tty.setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + process.stdout.write(cmd.helpInformation()); + cmd.emit('--help'); + process.exit(0); + } + } +} diff --git a/node_modules/express/node_modules/commander/package.json b/node_modules/express/node_modules/commander/package.json new file mode 100644 index 0000000..764dece --- /dev/null +++ b/node_modules/express/node_modules/commander/package.json @@ -0,0 +1,34 @@ +{ + "name": "commander", + "version": "0.6.1", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": {}, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.4.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "_id": "commander@0.6.1", + "_from": "commander@0.6.1" +} diff --git a/node_modules/express/node_modules/connect/.npmignore b/node_modules/express/node_modules/connect/.npmignore new file mode 100644 index 0000000..9046dde --- /dev/null +++ b/node_modules/express/node_modules/connect/.npmignore @@ -0,0 +1,12 @@ +*.markdown +*.md +.git* +Makefile +benchmarks/ +docs/ +examples/ +install.sh +support/ +test/ +.DS_Store +coverage.html diff --git a/node_modules/express/node_modules/connect/.travis.yml b/node_modules/express/node_modules/connect/.travis.yml new file mode 100644 index 0000000..3aeb3c5 --- /dev/null +++ b/node_modules/express/node_modules/connect/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - 0.9 \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/LICENSE b/node_modules/express/node_modules/connect/LICENSE new file mode 100644 index 0000000..0c5d22d --- /dev/null +++ b/node_modules/express/node_modules/connect/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/Readme.md b/node_modules/express/node_modules/connect/Readme.md new file mode 100644 index 0000000..7d65f9c --- /dev/null +++ b/node_modules/express/node_modules/connect/Readme.md @@ -0,0 +1,133 @@ +[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect) +# Connect + + Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance "plugins" known as _middleware_. + + Connect is bundled with over _20_ commonly used middleware, including + a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/). + +```js +var connect = require('connect') + , http = require('http'); + +var app = connect() + .use(connect.favicon()) + .use(connect.logger('dev')) + .use(connect.static('public')) + .use(connect.directory('public')) + .use(connect.cookieParser()) + .use(connect.session({ secret: 'my secret here' })) + .use(function(req, res){ + res.end('Hello from Connect!\n'); + }); + +http.createServer(app).listen(3000); +``` + +## Middleware + + - [csrf](http://www.senchalabs.org/connect/csrf.html) + - [basicAuth](http://www.senchalabs.org/connect/basicAuth.html) + - [bodyParser](http://www.senchalabs.org/connect/bodyParser.html) + - [json](http://www.senchalabs.org/connect/json.html) + - [multipart](http://www.senchalabs.org/connect/multipart.html) + - [urlencoded](http://www.senchalabs.org/connect/urlencoded.html) + - [cookieParser](http://www.senchalabs.org/connect/cookieParser.html) + - [directory](http://www.senchalabs.org/connect/directory.html) + - [compress](http://www.senchalabs.org/connect/compress.html) + - [errorHandler](http://www.senchalabs.org/connect/errorHandler.html) + - [favicon](http://www.senchalabs.org/connect/favicon.html) + - [limit](http://www.senchalabs.org/connect/limit.html) + - [logger](http://www.senchalabs.org/connect/logger.html) + - [methodOverride](http://www.senchalabs.org/connect/methodOverride.html) + - [query](http://www.senchalabs.org/connect/query.html) + - [responseTime](http://www.senchalabs.org/connect/responseTime.html) + - [session](http://www.senchalabs.org/connect/session.html) + - [static](http://www.senchalabs.org/connect/static.html) + - [staticCache](http://www.senchalabs.org/connect/staticCache.html) + - [vhost](http://www.senchalabs.org/connect/vhost.html) + - [subdomains](http://www.senchalabs.org/connect/subdomains.html) + - [cookieSession](http://www.senchalabs.org/connect/cookieSession.html) + +## Running Tests + +first: + + $ npm install -d + +then: + + $ make test + +## Authors + + Below is the output from [git-summary](http://github.com/visionmedia/git-extras). + + + project: connect + commits: 2033 + active : 301 days + files : 171 + authors: + 1414 Tj Holowaychuk 69.6% + 298 visionmedia 14.7% + 191 Tim Caswell 9.4% + 51 TJ Holowaychuk 2.5% + 10 Ryan Olds 0.5% + 8 Astro 0.4% + 5 Nathan Rajlich 0.2% + 5 Jakub Nešetřil 0.2% + 3 Daniel Dickison 0.1% + 3 David Rio Deiros 0.1% + 3 Alexander Simmerl 0.1% + 3 Andreas Lind Petersen 0.1% + 2 Aaron Heckmann 0.1% + 2 Jacques Crocker 0.1% + 2 Fabian Jakobs 0.1% + 2 Brian J Brennan 0.1% + 2 Adam Malcontenti-Wilson 0.1% + 2 Glen Mailer 0.1% + 2 James Campos 0.1% + 1 Trent Mick 0.0% + 1 Troy Kruthoff 0.0% + 1 Wei Zhu 0.0% + 1 comerc 0.0% + 1 darobin 0.0% + 1 nateps 0.0% + 1 Marco Sanson 0.0% + 1 Arthur Taylor 0.0% + 1 Aseem Kishore 0.0% + 1 Bart Teeuwisse 0.0% + 1 Cameron Howey 0.0% + 1 Chad Weider 0.0% + 1 Craig Barnes 0.0% + 1 Eran Hammer-Lahav 0.0% + 1 Gregory McWhirter 0.0% + 1 Guillermo Rauch 0.0% + 1 Jae Kwon 0.0% + 1 Jakub Nesetril 0.0% + 1 Joshua Peek 0.0% + 1 Jxck 0.0% + 1 AJ ONeal 0.0% + 1 Michael Hemesath 0.0% + 1 Morten Siebuhr 0.0% + 1 Samori Gorse 0.0% + 1 Tom Jensen 0.0% + +## Node Compatibility + + Connect `< 1.x` is compatible with node 0.2.x + + + Connect `1.x` is compatible with node 0.4.x + + + Connect (_master_) `2.x` is compatible with node 0.6.x + +## CLA + + [http://sencha.com/cla](http://sencha.com/cla) + +## License + +View the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/). diff --git a/node_modules/express/node_modules/connect/index.js b/node_modules/express/node_modules/connect/index.js new file mode 100644 index 0000000..23240ee --- /dev/null +++ b/node_modules/express/node_modules/connect/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.CONNECT_COV + ? require('./lib-cov/connect') + : require('./lib/connect'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib-cov/cache.js b/node_modules/express/node_modules/connect/lib-cov/cache.js new file mode 100644 index 0000000..af6cd2f --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/cache.js @@ -0,0 +1,68 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['cache.js']) { + _$jscoverage['cache.js'] = []; + _$jscoverage['cache.js'][12] = 0; + _$jscoverage['cache.js'][21] = 0; + _$jscoverage['cache.js'][22] = 0; + _$jscoverage['cache.js'][23] = 0; + _$jscoverage['cache.js'][24] = 0; + _$jscoverage['cache.js'][35] = 0; + _$jscoverage['cache.js'][36] = 0; + _$jscoverage['cache.js'][37] = 0; + _$jscoverage['cache.js'][47] = 0; + _$jscoverage['cache.js'][48] = 0; + _$jscoverage['cache.js'][59] = 0; + _$jscoverage['cache.js'][60] = 0; + _$jscoverage['cache.js'][71] = 0; + _$jscoverage['cache.js'][73] = 0; + _$jscoverage['cache.js'][76] = 0; + _$jscoverage['cache.js'][78] = 0; + _$jscoverage['cache.js'][79] = 0; + _$jscoverage['cache.js'][80] = 0; +} +_$jscoverage['cache.js'][12]++; +module.exports = Cache; +_$jscoverage['cache.js'][21]++; +function Cache(limit) { + _$jscoverage['cache.js'][22]++; + this.store = {}; + _$jscoverage['cache.js'][23]++; + this.keys = []; + _$jscoverage['cache.js'][24]++; + this.limit = limit; +} +_$jscoverage['cache.js'][35]++; +Cache.prototype.touch = (function (key, i) { + _$jscoverage['cache.js'][36]++; + this.keys.splice(i, 1); + _$jscoverage['cache.js'][37]++; + this.keys.push(key); +}); +_$jscoverage['cache.js'][47]++; +Cache.prototype.remove = (function (key) { + _$jscoverage['cache.js'][48]++; + delete this.store[key]; +}); +_$jscoverage['cache.js'][59]++; +Cache.prototype.get = (function (key) { + _$jscoverage['cache.js'][60]++; + return this.store[key]; +}); +_$jscoverage['cache.js'][71]++; +Cache.prototype.add = (function (key) { + _$jscoverage['cache.js'][73]++; + var len = this.keys.push(key); + _$jscoverage['cache.js'][76]++; + if (len > this.limit) { + _$jscoverage['cache.js'][76]++; + this.remove(this.keys.shift()); + } + _$jscoverage['cache.js'][78]++; + var arr = this.store[key] = []; + _$jscoverage['cache.js'][79]++; + arr.createdAt = new Date(); + _$jscoverage['cache.js'][80]++; + return arr; +}); +_$jscoverage['cache.js'].source = ["","/*!"," * Connect - Cache"," * Copyright(c) 2011 Sencha Inc."," * MIT Licensed"," */","","/**"," * Expose `Cache`."," */","","module.exports = Cache;","","/**"," * LRU cache store."," *"," * @param {Number} limit"," * @api private"," */","","function Cache(limit) {"," this.store = {};"," this.keys = [];"," this.limit = limit;","}","","/**"," * Touch `key`, promoting the object."," *"," * @param {String} key"," * @param {Number} i"," * @api private"," */","","Cache.prototype.touch = function(key, i){"," this.keys.splice(i,1);"," this.keys.push(key);","};","","/**"," * Remove `key`."," *"," * @param {String} key"," * @api private"," */","","Cache.prototype.remove = function(key){"," delete this.store[key];","};","","/**"," * Get the object stored for `key`."," *"," * @param {String} key"," * @return {Array}"," * @api private"," */","","Cache.prototype.get = function(key){"," return this.store[key];","};","","/**"," * Add a cache `key`."," *"," * @param {String} key"," * @return {Array}"," * @api private"," */","","Cache.prototype.add = function(key){"," // initialize store"," var len = this.keys.push(key);",""," // limit reached, invalidate LRU"," if (len > this.limit) this.remove(this.keys.shift());",""," var arr = this.store[key] = [];"," arr.createdAt = new Date;"," return arr;","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/connect.js b/node_modules/express/node_modules/connect/lib-cov/connect.js new file mode 100644 index 0000000..f811bb8 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/connect.js @@ -0,0 +1,93 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['connect.js']) { + _$jscoverage['connect.js'] = []; + _$jscoverage['connect.js'][13] = 0; + _$jscoverage['connect.js'][22] = 0; + _$jscoverage['connect.js'][26] = 0; + _$jscoverage['connect.js'][32] = 0; + _$jscoverage['connect.js'][38] = 0; + _$jscoverage['connect.js'][44] = 0; + _$jscoverage['connect.js'][50] = 0; + _$jscoverage['connect.js'][56] = 0; + _$jscoverage['connect.js'][65] = 0; + _$jscoverage['connect.js'][66] = 0; + _$jscoverage['connect.js'][67] = 0; + _$jscoverage['connect.js'][68] = 0; + _$jscoverage['connect.js'][69] = 0; + _$jscoverage['connect.js'][70] = 0; + _$jscoverage['connect.js'][71] = 0; + _$jscoverage['connect.js'][72] = 0; + _$jscoverage['connect.js'][74] = 0; + _$jscoverage['connect.js'][75] = 0; + _$jscoverage['connect.js'][81] = 0; + _$jscoverage['connect.js'][87] = 0; + _$jscoverage['connect.js'][88] = 0; + _$jscoverage['connect.js'][89] = 0; + _$jscoverage['connect.js'][90] = 0; + _$jscoverage['connect.js'][91] = 0; + _$jscoverage['connect.js'][92] = 0; +} +_$jscoverage['connect.js'][13]++; +var EventEmitter = require("events").EventEmitter, proto = require("./proto"), utils = require("./utils"), path = require("path"), basename = path.basename, fs = require("fs"); +_$jscoverage['connect.js'][22]++; +require("./patch"); +_$jscoverage['connect.js'][26]++; +exports = module.exports = createServer; +_$jscoverage['connect.js'][32]++; +exports.version = "2.6.1"; +_$jscoverage['connect.js'][38]++; +exports.mime = require("./middleware/static").mime; +_$jscoverage['connect.js'][44]++; +exports.proto = proto; +_$jscoverage['connect.js'][50]++; +exports.middleware = {}; +_$jscoverage['connect.js'][56]++; +exports.utils = utils; +_$jscoverage['connect.js'][65]++; +function createServer() { + _$jscoverage['connect.js'][66]++; + function app(req, res) { + _$jscoverage['connect.js'][66]++; + app.handle(req, res); +} + _$jscoverage['connect.js'][67]++; + utils.merge(app, proto); + _$jscoverage['connect.js'][68]++; + utils.merge(app, EventEmitter.prototype); + _$jscoverage['connect.js'][69]++; + app.route = "/"; + _$jscoverage['connect.js'][70]++; + app.stack = []; + _$jscoverage['connect.js'][71]++; + for (var i = 0; i < arguments.length; ++i) { + _$jscoverage['connect.js'][72]++; + app.use(arguments[i]); +} + _$jscoverage['connect.js'][74]++; + return app; +} +_$jscoverage['connect.js'][75]++; +; +_$jscoverage['connect.js'][81]++; +createServer.createServer = createServer; +_$jscoverage['connect.js'][87]++; +fs.readdirSync(__dirname + "/middleware").forEach((function (filename) { + _$jscoverage['connect.js'][88]++; + if (! /\.js$/.test(filename)) { + _$jscoverage['connect.js'][88]++; + return; + } + _$jscoverage['connect.js'][89]++; + var name = basename(filename, ".js"); + _$jscoverage['connect.js'][90]++; + function load() { + _$jscoverage['connect.js'][90]++; + return require("./middleware/" + name); +} + _$jscoverage['connect.js'][91]++; + exports.middleware.__defineGetter__(name, load); + _$jscoverage['connect.js'][92]++; + exports.__defineGetter__(name, load); +})); +_$jscoverage['connect.js'].source = ["","/*!"," * Connect"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var EventEmitter = require('events').EventEmitter"," , proto = require('./proto')"," , utils = require('./utils')"," , path = require('path')"," , basename = path.basename"," , fs = require('fs');","","// node patches","","require('./patch');","","// expose createServer() as the module","","exports = module.exports = createServer;","","/**"," * Framework version."," */","","exports.version = '2.6.1';","","/**"," * Expose mime module."," */","","exports.mime = require('./middleware/static').mime;","","/**"," * Expose the prototype."," */","","exports.proto = proto;","","/**"," * Auto-load middleware getters."," */","","exports.middleware = {};","","/**"," * Expose utilities."," */","","exports.utils = utils;","","/**"," * Create a new connect server."," *"," * @return {Function}"," * @api public"," */","","function createServer() {"," function app(req, res){ app.handle(req, res); }"," utils.merge(app, proto);"," utils.merge(app, EventEmitter.prototype);"," app.route = '/';"," app.stack = [];"," for (var i = 0; i < arguments.length; ++i) {"," app.use(arguments[i]);"," }"," return app;","};","","/**"," * Support old `.createServer()` method."," */","","createServer.createServer = createServer;","","/**"," * Auto-load bundled middleware with getters."," */","","fs.readdirSync(__dirname + '/middleware').forEach(function(filename){"," if (!/\\.js$/.test(filename)) return;"," var name = basename(filename, '.js');"," function load(){ return require('./middleware/' + name); }"," exports.middleware.__defineGetter__(name, load);"," exports.__defineGetter__(name, load);","});"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/index.js b/node_modules/express/node_modules/connect/lib-cov/index.js new file mode 100644 index 0000000..e6bb1c7 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/index.js @@ -0,0 +1,6 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['index.js']) { + _$jscoverage['index.js'] = []; +} +_$jscoverage['index.js'].source = ["","/**"," * Connect is a middleware framework for node,"," * shipping with over 18 bundled middleware and a rich selection of"," * 3rd-party middleware."," *"," * var app = connect()"," * .use(connect.logger('dev'))"," * .use(connect.static('public'))"," * .use(function(req, res){"," * res.end('hello world\\n');"," * })"," * .listen(3000);"," * "," * Installation:"," * "," * $ npm install connect"," *"," * Middleware:"," *"," * - [logger](logger.html) request logger with custom format support"," * - [csrf](csrf.html) Cross-site request forgery protection"," * - [compress](compress.html) Gzip compression middleware"," * - [basicAuth](basicAuth.html) basic http authentication"," * - [bodyParser](bodyParser.html) extensible request body parser"," * - [json](json.html) application/json parser"," * - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser"," * - [multipart](multipart.html) multipart/form-data parser"," * - [timeout](timeout.html) request timeouts"," * - [cookieParser](cookieParser.html) cookie parser"," * - [session](session.html) session management support with bundled MemoryStore"," * - [cookieSession](cookieSession.html) cookie-based session support"," * - [methodOverride](methodOverride.html) faux HTTP method support"," * - [responseTime](responseTime.html) calculates response-time and exposes via X-Response-Time"," * - [staticCache](staticCache.html) memory cache layer for the static() middleware"," * - [static](static.html) streaming static file server supporting `Range` and more"," * - [directory](directory.html) directory listing middleware"," * - [vhost](vhost.html) virtual host sub-domain mapping middleware"," * - [favicon](favicon.html) efficient favicon server (with default icon)"," * - [limit](limit.html) limit the bytesize of request bodies"," * - [query](query.html) automatic querystring parser, populating `req.query`"," * - [errorHandler](errorHandler.html) flexible error handler"," *"," * Links:"," * "," * - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware"," * - GitHub [repository](http://github.com/senchalabs/connect)"," * - [test documentation](https://github.com/senchalabs/connect/blob/gh-pages/tests.md)"," * "," */"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/basicAuth.js b/node_modules/express/node_modules/connect/lib-cov/middleware/basicAuth.js new file mode 100644 index 0000000..c9e7d63 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/basicAuth.js @@ -0,0 +1,128 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/basicAuth.js']) { + _$jscoverage['middleware/basicAuth.js'] = []; + _$jscoverage['middleware/basicAuth.js'][13] = 0; + _$jscoverage['middleware/basicAuth.js'][48] = 0; + _$jscoverage['middleware/basicAuth.js'][49] = 0; + _$jscoverage['middleware/basicAuth.js'][52] = 0; + _$jscoverage['middleware/basicAuth.js'][53] = 0; + _$jscoverage['middleware/basicAuth.js'][54] = 0; + _$jscoverage['middleware/basicAuth.js'][55] = 0; + _$jscoverage['middleware/basicAuth.js'][56] = 0; + _$jscoverage['middleware/basicAuth.js'][57] = 0; + _$jscoverage['middleware/basicAuth.js'][58] = 0; + _$jscoverage['middleware/basicAuth.js'][62] = 0; + _$jscoverage['middleware/basicAuth.js'][64] = 0; + _$jscoverage['middleware/basicAuth.js'][65] = 0; + _$jscoverage['middleware/basicAuth.js'][67] = 0; + _$jscoverage['middleware/basicAuth.js'][68] = 0; + _$jscoverage['middleware/basicAuth.js'][70] = 0; + _$jscoverage['middleware/basicAuth.js'][72] = 0; + _$jscoverage['middleware/basicAuth.js'][74] = 0; + _$jscoverage['middleware/basicAuth.js'][78] = 0; + _$jscoverage['middleware/basicAuth.js'][80] = 0; + _$jscoverage['middleware/basicAuth.js'][84] = 0; + _$jscoverage['middleware/basicAuth.js'][85] = 0; + _$jscoverage['middleware/basicAuth.js'][86] = 0; + _$jscoverage['middleware/basicAuth.js'][87] = 0; + _$jscoverage['middleware/basicAuth.js'][88] = 0; + _$jscoverage['middleware/basicAuth.js'][89] = 0; + _$jscoverage['middleware/basicAuth.js'][90] = 0; + _$jscoverage['middleware/basicAuth.js'][94] = 0; + _$jscoverage['middleware/basicAuth.js'][95] = 0; + _$jscoverage['middleware/basicAuth.js'][96] = 0; + _$jscoverage['middleware/basicAuth.js'][98] = 0; +} +_$jscoverage['middleware/basicAuth.js'][13]++; +var utils = require("../utils"), unauthorized = utils.unauthorized; +_$jscoverage['middleware/basicAuth.js'][48]++; +module.exports = (function basicAuth(callback, realm) { + _$jscoverage['middleware/basicAuth.js'][49]++; + var username, password; + _$jscoverage['middleware/basicAuth.js'][52]++; + if ("string" == typeof callback) { + _$jscoverage['middleware/basicAuth.js'][53]++; + username = callback; + _$jscoverage['middleware/basicAuth.js'][54]++; + password = realm; + _$jscoverage['middleware/basicAuth.js'][55]++; + if ("string" != typeof password) { + _$jscoverage['middleware/basicAuth.js'][55]++; + throw new Error("password argument required"); + } + _$jscoverage['middleware/basicAuth.js'][56]++; + realm = arguments[2]; + _$jscoverage['middleware/basicAuth.js'][57]++; + callback = (function (user, pass) { + _$jscoverage['middleware/basicAuth.js'][58]++; + return user == username && pass == password; +}); + } + _$jscoverage['middleware/basicAuth.js'][62]++; + realm = realm || "Authorization Required"; + _$jscoverage['middleware/basicAuth.js'][64]++; + return (function (req, res, next) { + _$jscoverage['middleware/basicAuth.js'][65]++; + var authorization = req.headers.authorization; + _$jscoverage['middleware/basicAuth.js'][67]++; + if (req.user) { + _$jscoverage['middleware/basicAuth.js'][67]++; + return next(); + } + _$jscoverage['middleware/basicAuth.js'][68]++; + if (! authorization) { + _$jscoverage['middleware/basicAuth.js'][68]++; + return unauthorized(res, realm); + } + _$jscoverage['middleware/basicAuth.js'][70]++; + var parts = authorization.split(" "); + _$jscoverage['middleware/basicAuth.js'][72]++; + if (parts.length !== 2) { + _$jscoverage['middleware/basicAuth.js'][72]++; + return next(utils.error(400)); + } + _$jscoverage['middleware/basicAuth.js'][74]++; + var scheme = parts[0], credentials = new Buffer(parts[1], "base64").toString(), index = credentials.indexOf(":"); + _$jscoverage['middleware/basicAuth.js'][78]++; + if ("Basic" != scheme || index < 0) { + _$jscoverage['middleware/basicAuth.js'][78]++; + return next(utils.error(400)); + } + _$jscoverage['middleware/basicAuth.js'][80]++; + var user = credentials.slice(0, index), pass = credentials.slice(index + 1); + _$jscoverage['middleware/basicAuth.js'][84]++; + if (callback.length >= 3) { + _$jscoverage['middleware/basicAuth.js'][85]++; + var pause = utils.pause(req); + _$jscoverage['middleware/basicAuth.js'][86]++; + callback(user, pass, (function (err, user) { + _$jscoverage['middleware/basicAuth.js'][87]++; + if (err || ! user) { + _$jscoverage['middleware/basicAuth.js'][87]++; + return unauthorized(res, realm); + } + _$jscoverage['middleware/basicAuth.js'][88]++; + req.user = req.remoteUser = user; + _$jscoverage['middleware/basicAuth.js'][89]++; + next(); + _$jscoverage['middleware/basicAuth.js'][90]++; + pause.resume(); +})); + } + else { + _$jscoverage['middleware/basicAuth.js'][94]++; + if (callback(user, pass)) { + _$jscoverage['middleware/basicAuth.js'][95]++; + req.user = req.remoteUser = user; + _$jscoverage['middleware/basicAuth.js'][96]++; + next(); + } + else { + _$jscoverage['middleware/basicAuth.js'][98]++; + unauthorized(res, realm); + } + } +}); +}); +_$jscoverage['middleware/basicAuth.js'].source = ["","/*!"," * Connect - basicAuth"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils')"," , unauthorized = utils.unauthorized;","","/**"," * Basic Auth:"," *"," * Enfore basic authentication by providing a `callback(user, pass)`,"," * which must return `true` in order to gain access. Alternatively an async"," * method is provided as well, invoking `callback(user, pass, callback)`. Populates"," * `req.user`. The final alternative is simply passing username / password"," * strings."," *"," * Simple username and password"," *"," * connect(connect.basicAuth('username', 'password'));"," *"," * Callback verification"," *"," * connect()"," * .use(connect.basicAuth(function(user, pass){"," * return 'tj' == user & 'wahoo' == pass;"," * }))"," *"," * Async callback verification, accepting `fn(err, user)`."," *"," * connect()"," * .use(connect.basicAuth(function(user, pass, fn){"," * User.authenticate({ user: user, pass: pass }, fn);"," * }))"," *"," * @param {Function|String} callback or username"," * @param {String} realm"," * @api public"," */","","module.exports = function basicAuth(callback, realm) {"," var username, password;",""," // user / pass strings"," if ('string' == typeof callback) {"," username = callback;"," password = realm;"," if ('string' != typeof password) throw new Error('password argument required');"," realm = arguments[2];"," callback = function(user, pass){"," return user == username && pass == password;"," }"," }",""," realm = realm || 'Authorization Required';",""," return function(req, res, next) {"," var authorization = req.headers.authorization;",""," if (req.user) return next();"," if (!authorization) return unauthorized(res, realm);",""," var parts = authorization.split(' ');",""," if (parts.length !== 2) return next(utils.error(400));",""," var scheme = parts[0]"," , credentials = new Buffer(parts[1], 'base64').toString()"," , index = credentials.indexOf(':');",""," if ('Basic' != scheme || index < 0) return next(utils.error(400));"," "," var user = credentials.slice(0, index)"," , pass = credentials.slice(index + 1);",""," // async"," if (callback.length >= 3) {"," var pause = utils.pause(req);"," callback(user, pass, function(err, user){"," if (err || !user) return unauthorized(res, realm);"," req.user = req.remoteUser = user;"," next();"," pause.resume();"," });"," // sync"," } else {"," if (callback(user, pass)) {"," req.user = req.remoteUser = user;"," next();"," } else {"," unauthorized(res, realm);"," }"," }"," }","};",""]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/bodyParser.js b/node_modules/express/node_modules/connect/lib-cov/middleware/bodyParser.js new file mode 100644 index 0000000..a108b97 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/bodyParser.js @@ -0,0 +1,43 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/bodyParser.js']) { + _$jscoverage['middleware/bodyParser.js'] = []; + _$jscoverage['middleware/bodyParser.js'][13] = 0; + _$jscoverage['middleware/bodyParser.js'][47] = 0; + _$jscoverage['middleware/bodyParser.js'][48] = 0; + _$jscoverage['middleware/bodyParser.js'][52] = 0; + _$jscoverage['middleware/bodyParser.js'][53] = 0; + _$jscoverage['middleware/bodyParser.js'][54] = 0; + _$jscoverage['middleware/bodyParser.js'][55] = 0; + _$jscoverage['middleware/bodyParser.js'][56] = 0; + _$jscoverage['middleware/bodyParser.js'][57] = 0; +} +_$jscoverage['middleware/bodyParser.js'][13]++; +var multipart = require("./multipart"), urlencoded = require("./urlencoded"), json = require("./json"); +_$jscoverage['middleware/bodyParser.js'][47]++; +exports = module.exports = (function bodyParser(options) { + _$jscoverage['middleware/bodyParser.js'][48]++; + var _urlencoded = urlencoded(options), _multipart = multipart(options), _json = json(options); + _$jscoverage['middleware/bodyParser.js'][52]++; + return (function bodyParser(req, res, next) { + _$jscoverage['middleware/bodyParser.js'][53]++; + _json(req, res, (function (err) { + _$jscoverage['middleware/bodyParser.js'][54]++; + if (err) { + _$jscoverage['middleware/bodyParser.js'][54]++; + return next(err); + } + _$jscoverage['middleware/bodyParser.js'][55]++; + _urlencoded(req, res, (function (err) { + _$jscoverage['middleware/bodyParser.js'][56]++; + if (err) { + _$jscoverage['middleware/bodyParser.js'][56]++; + return next(err); + } + _$jscoverage['middleware/bodyParser.js'][57]++; + _multipart(req, res, next); +})); +})); +}); +}); +_$jscoverage['middleware/bodyParser.js'].source = ["","/*!"," * Connect - bodyParser"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var multipart = require('./multipart')"," , urlencoded = require('./urlencoded')"," , json = require('./json');","","/**"," * Body parser:"," * "," * Parse request bodies, supports _application/json_,"," * _application/x-www-form-urlencoded_, and _multipart/form-data_."," *"," * This is equivalent to: "," *"," * app.use(connect.json());"," * app.use(connect.urlencoded());"," * app.use(connect.multipart());"," *"," * Examples:"," *"," * connect()"," * .use(connect.bodyParser())"," * .use(function(req, res) {"," * res.end('viewing user ' + req.body.user.name);"," * });"," *"," * $ curl -d 'user[name]=tj' http://local/"," * $ curl -d '{\"user\":{\"name\":\"tj\"}}' -H \"Content-Type: application/json\" http://local/"," *"," * View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info."," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function bodyParser(options){"," var _urlencoded = urlencoded(options)"," , _multipart = multipart(options)"," , _json = json(options);",""," return function bodyParser(req, res, next) {"," _json(req, res, function(err){"," if (err) return next(err);"," _urlencoded(req, res, function(err){"," if (err) return next(err);"," _multipart(req, res, next);"," });"," });"," }","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/compress.js b/node_modules/express/node_modules/connect/lib-cov/middleware/compress.js new file mode 100644 index 0000000..aebd5f1 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/compress.js @@ -0,0 +1,159 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/compress.js']) { + _$jscoverage['middleware/compress.js'] = []; + _$jscoverage['middleware/compress.js'][12] = 0; + _$jscoverage['middleware/compress.js'][18] = 0; + _$jscoverage['middleware/compress.js'][27] = 0; + _$jscoverage['middleware/compress.js'][28] = 0; + _$jscoverage['middleware/compress.js'][61] = 0; + _$jscoverage['middleware/compress.js'][62] = 0; + _$jscoverage['middleware/compress.js'][63] = 0; + _$jscoverage['middleware/compress.js'][66] = 0; + _$jscoverage['middleware/compress.js'][67] = 0; + _$jscoverage['middleware/compress.js'][74] = 0; + _$jscoverage['middleware/compress.js'][78] = 0; + _$jscoverage['middleware/compress.js'][79] = 0; + _$jscoverage['middleware/compress.js'][80] = 0; + _$jscoverage['middleware/compress.js'][85] = 0; + _$jscoverage['middleware/compress.js'][86] = 0; + _$jscoverage['middleware/compress.js'][87] = 0; + _$jscoverage['middleware/compress.js'][92] = 0; + _$jscoverage['middleware/compress.js'][93] = 0; + _$jscoverage['middleware/compress.js'][96] = 0; + _$jscoverage['middleware/compress.js'][99] = 0; + _$jscoverage['middleware/compress.js'][102] = 0; + _$jscoverage['middleware/compress.js'][105] = 0; + _$jscoverage['middleware/compress.js'][108] = 0; + _$jscoverage['middleware/compress.js'][111] = 0; + _$jscoverage['middleware/compress.js'][112] = 0; + _$jscoverage['middleware/compress.js'][113] = 0; + _$jscoverage['middleware/compress.js'][114] = 0; + _$jscoverage['middleware/compress.js'][115] = 0; + _$jscoverage['middleware/compress.js'][121] = 0; + _$jscoverage['middleware/compress.js'][124] = 0; + _$jscoverage['middleware/compress.js'][127] = 0; + _$jscoverage['middleware/compress.js'][128] = 0; + _$jscoverage['middleware/compress.js'][132] = 0; + _$jscoverage['middleware/compress.js'][133] = 0; + _$jscoverage['middleware/compress.js'][136] = 0; + _$jscoverage['middleware/compress.js'][137] = 0; + _$jscoverage['middleware/compress.js'][140] = 0; + _$jscoverage['middleware/compress.js'][141] = 0; + _$jscoverage['middleware/compress.js'][145] = 0; +} +_$jscoverage['middleware/compress.js'][12]++; +var zlib = require("zlib"); +_$jscoverage['middleware/compress.js'][18]++; +exports.methods = {gzip: zlib.createGzip, deflate: zlib.createDeflate}; +_$jscoverage['middleware/compress.js'][27]++; +exports.filter = (function (req, res) { + _$jscoverage['middleware/compress.js'][28]++; + return /json|text|javascript/.test(res.getHeader("Content-Type")); +}); +_$jscoverage['middleware/compress.js'][61]++; +module.exports = (function compress(options) { + _$jscoverage['middleware/compress.js'][62]++; + options = options || {}; + _$jscoverage['middleware/compress.js'][63]++; + var names = Object.keys(exports.methods), filter = options.filter || exports.filter; + _$jscoverage['middleware/compress.js'][66]++; + return (function (req, res, next) { + _$jscoverage['middleware/compress.js'][67]++; + var accept = req.headers["accept-encoding"], write = res.write, end = res.end, stream, method; + _$jscoverage['middleware/compress.js'][74]++; + res.setHeader("Vary", "Accept-Encoding"); + _$jscoverage['middleware/compress.js'][78]++; + res.write = (function (chunk, encoding) { + _$jscoverage['middleware/compress.js'][79]++; + if (! this.headerSent) { + _$jscoverage['middleware/compress.js'][79]++; + this._implicitHeader(); + } + _$jscoverage['middleware/compress.js'][80]++; + return stream? stream.write(new Buffer(chunk, encoding)): write.call(res, chunk, encoding); +}); + _$jscoverage['middleware/compress.js'][85]++; + res.end = (function (chunk, encoding) { + _$jscoverage['middleware/compress.js'][86]++; + if (chunk) { + _$jscoverage['middleware/compress.js'][86]++; + this.write(chunk, encoding); + } + _$jscoverage['middleware/compress.js'][87]++; + return stream? stream.end(): end.call(res); +}); + _$jscoverage['middleware/compress.js'][92]++; + res.on("header", (function () { + _$jscoverage['middleware/compress.js'][93]++; + var encoding = res.getHeader("Content-Encoding") || "identity"; + _$jscoverage['middleware/compress.js'][96]++; + if ("identity" != encoding) { + _$jscoverage['middleware/compress.js'][96]++; + return; + } + _$jscoverage['middleware/compress.js'][99]++; + if (! filter(req, res)) { + _$jscoverage['middleware/compress.js'][99]++; + return; + } + _$jscoverage['middleware/compress.js'][102]++; + if (! accept) { + _$jscoverage['middleware/compress.js'][102]++; + return; + } + _$jscoverage['middleware/compress.js'][105]++; + if ("HEAD" == req.method) { + _$jscoverage['middleware/compress.js'][105]++; + return; + } + _$jscoverage['middleware/compress.js'][108]++; + if ("*" == accept.trim()) { + _$jscoverage['middleware/compress.js'][108]++; + method = "gzip"; + } + _$jscoverage['middleware/compress.js'][111]++; + if (! method) { + _$jscoverage['middleware/compress.js'][112]++; + for (var i = 0, len = names.length; i < len; ++i) { + _$jscoverage['middleware/compress.js'][113]++; + if (~ accept.indexOf(names[i])) { + _$jscoverage['middleware/compress.js'][114]++; + method = names[i]; + _$jscoverage['middleware/compress.js'][115]++; + break; + } +} + } + _$jscoverage['middleware/compress.js'][121]++; + if (! method) { + _$jscoverage['middleware/compress.js'][121]++; + return; + } + _$jscoverage['middleware/compress.js'][124]++; + stream = exports.methods[method](options); + _$jscoverage['middleware/compress.js'][127]++; + res.setHeader("Content-Encoding", method); + _$jscoverage['middleware/compress.js'][128]++; + res.removeHeader("Content-Length"); + _$jscoverage['middleware/compress.js'][132]++; + stream.on("data", (function (chunk) { + _$jscoverage['middleware/compress.js'][133]++; + write.call(res, chunk); +})); + _$jscoverage['middleware/compress.js'][136]++; + stream.on("end", (function () { + _$jscoverage['middleware/compress.js'][137]++; + end.call(res); +})); + _$jscoverage['middleware/compress.js'][140]++; + stream.on("drain", (function () { + _$jscoverage['middleware/compress.js'][141]++; + res.emit("drain"); +})); +})); + _$jscoverage['middleware/compress.js'][145]++; + next(); +}); +}); +_$jscoverage['middleware/compress.js'].source = ["/*!"," * Connect - compress"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var zlib = require('zlib');","","/**"," * Supported content-encoding methods."," */","","exports.methods = {"," gzip: zlib.createGzip"," , deflate: zlib.createDeflate","};","","/**"," * Default filter function."," */","","exports.filter = function(req, res){"," return /json|text|javascript/.test(res.getHeader('Content-Type'));","};","","/**"," * Compress:"," *"," * Compress response data with gzip/deflate."," *"," * Filter:"," *"," * A `filter` callback function may be passed to"," * replace the default logic of:"," *"," * exports.filter = function(req, res){"," * return /json|text|javascript/.test(res.getHeader('Content-Type'));"," * };"," *"," * Options:"," *"," * All remaining options are passed to the gzip/deflate"," * creation functions. Consult node's docs for additional details."," *"," * - `chunkSize` (default: 16*1024)"," * - `windowBits`"," * - `level`: 0-9 where 0 is no compression, and 9 is slow but best compression"," * - `memLevel`: 1-9 low is slower but uses less memory, high is fast but uses more"," * - `strategy`: compression strategy"," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","module.exports = function compress(options) {"," options = options || {};"," var names = Object.keys(exports.methods)"," , filter = options.filter || exports.filter;",""," return function(req, res, next){"," var accept = req.headers['accept-encoding']"," , write = res.write"," , end = res.end"," , stream"," , method;",""," // vary"," res.setHeader('Vary', 'Accept-Encoding');",""," // proxy",""," res.write = function(chunk, encoding){"," if (!this.headerSent) this._implicitHeader();"," return stream"," ? stream.write(new Buffer(chunk, encoding))"," : write.call(res, chunk, encoding);"," };",""," res.end = function(chunk, encoding){"," if (chunk) this.write(chunk, encoding);"," return stream"," ? stream.end()"," : end.call(res);"," };",""," res.on('header', function(){"," var encoding = res.getHeader('Content-Encoding') || 'identity';",""," // already encoded"," if ('identity' != encoding) return; ",""," // default request filter"," if (!filter(req, res)) return;",""," // SHOULD use identity"," if (!accept) return;",""," // head"," if ('HEAD' == req.method) return;",""," // default to gzip"," if ('*' == accept.trim()) method = 'gzip';",""," // compression method"," if (!method) {"," for (var i = 0, len = names.length; i < len; ++i) {"," if (~accept.indexOf(names[i])) {"," method = names[i];"," break;"," }"," }"," }",""," // compression method"," if (!method) return;",""," // compression stream"," stream = exports.methods[method](options);",""," // header fields"," res.setHeader('Content-Encoding', method);"," res.removeHeader('Content-Length');",""," // compression",""," stream.on('data', function(chunk){"," write.call(res, chunk);"," });",""," stream.on('end', function(){"," end.call(res);"," });",""," stream.on('drain', function() {"," res.emit('drain');"," });"," });",""," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/cookieParser.js b/node_modules/express/node_modules/connect/lib-cov/middleware/cookieParser.js new file mode 100644 index 0000000..7f462d1 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/cookieParser.js @@ -0,0 +1,70 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/cookieParser.js']) { + _$jscoverage['middleware/cookieParser.js'] = []; + _$jscoverage['middleware/cookieParser.js'][13] = 0; + _$jscoverage['middleware/cookieParser.js'][38] = 0; + _$jscoverage['middleware/cookieParser.js'][39] = 0; + _$jscoverage['middleware/cookieParser.js'][40] = 0; + _$jscoverage['middleware/cookieParser.js'][41] = 0; + _$jscoverage['middleware/cookieParser.js'][43] = 0; + _$jscoverage['middleware/cookieParser.js'][44] = 0; + _$jscoverage['middleware/cookieParser.js'][45] = 0; + _$jscoverage['middleware/cookieParser.js'][47] = 0; + _$jscoverage['middleware/cookieParser.js'][48] = 0; + _$jscoverage['middleware/cookieParser.js'][49] = 0; + _$jscoverage['middleware/cookieParser.js'][50] = 0; + _$jscoverage['middleware/cookieParser.js'][51] = 0; + _$jscoverage['middleware/cookieParser.js'][52] = 0; + _$jscoverage['middleware/cookieParser.js'][54] = 0; + _$jscoverage['middleware/cookieParser.js'][56] = 0; + _$jscoverage['middleware/cookieParser.js'][57] = 0; + _$jscoverage['middleware/cookieParser.js'][60] = 0; +} +_$jscoverage['middleware/cookieParser.js'][13]++; +var utils = require("./../utils"), cookie = require("cookie"); +_$jscoverage['middleware/cookieParser.js'][38]++; +module.exports = (function cookieParser(secret) { + _$jscoverage['middleware/cookieParser.js'][39]++; + return (function cookieParser(req, res, next) { + _$jscoverage['middleware/cookieParser.js'][40]++; + if (req.cookies) { + _$jscoverage['middleware/cookieParser.js'][40]++; + return next(); + } + _$jscoverage['middleware/cookieParser.js'][41]++; + var cookies = req.headers.cookie; + _$jscoverage['middleware/cookieParser.js'][43]++; + req.secret = secret; + _$jscoverage['middleware/cookieParser.js'][44]++; + req.cookies = {}; + _$jscoverage['middleware/cookieParser.js'][45]++; + req.signedCookies = {}; + _$jscoverage['middleware/cookieParser.js'][47]++; + if (cookies) { + _$jscoverage['middleware/cookieParser.js'][48]++; + try { + _$jscoverage['middleware/cookieParser.js'][49]++; + req.cookies = cookie.parse(cookies); + _$jscoverage['middleware/cookieParser.js'][50]++; + if (secret) { + _$jscoverage['middleware/cookieParser.js'][51]++; + req.signedCookies = utils.parseSignedCookies(req.cookies, secret); + _$jscoverage['middleware/cookieParser.js'][52]++; + req.signedCookies = utils.parseJSONCookies(req.signedCookies); + } + _$jscoverage['middleware/cookieParser.js'][54]++; + req.cookies = utils.parseJSONCookies(req.cookies); + } + catch (err) { + _$jscoverage['middleware/cookieParser.js'][56]++; + err.status = 400; + _$jscoverage['middleware/cookieParser.js'][57]++; + return next(err); + } + } + _$jscoverage['middleware/cookieParser.js'][60]++; + next(); +}); +}); +_$jscoverage['middleware/cookieParser.js'].source = ["","/*!"," * Connect - cookieParser"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('./../utils')"," , cookie = require('cookie');","","/**"," * Cookie parser:"," *"," * Parse _Cookie_ header and populate `req.cookies`"," * with an object keyed by the cookie names. Optionally"," * you may enabled signed cookie support by passing"," * a `secret` string, which assigns `req.secret` so"," * it may be used by other middleware."," *"," * Examples:"," *"," * connect()"," * .use(connect.cookieParser('optional secret string'))"," * .use(function(req, res, next){"," * res.end(JSON.stringify(req.cookies));"," * })"," *"," * @param {String} secret"," * @return {Function}"," * @api public"," */","","module.exports = function cookieParser(secret){"," return function cookieParser(req, res, next) {"," if (req.cookies) return next();"," var cookies = req.headers.cookie;",""," req.secret = secret;"," req.cookies = {};"," req.signedCookies = {};",""," if (cookies) {"," try {"," req.cookies = cookie.parse(cookies);"," if (secret) {"," req.signedCookies = utils.parseSignedCookies(req.cookies, secret);"," req.signedCookies = utils.parseJSONCookies(req.signedCookies);"," }"," req.cookies = utils.parseJSONCookies(req.cookies);"," } catch (err) {"," err.status = 400;"," return next(err);"," }"," }"," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/cookieSession.js b/node_modules/express/node_modules/connect/lib-cov/middleware/cookieSession.js new file mode 100644 index 0000000..e54fa47 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/cookieSession.js @@ -0,0 +1,132 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/cookieSession.js']) { + _$jscoverage['middleware/cookieSession.js'] = []; + _$jscoverage['middleware/cookieSession.js'][12] = 0; + _$jscoverage['middleware/cookieSession.js'][46] = 0; + _$jscoverage['middleware/cookieSession.js'][48] = 0; + _$jscoverage['middleware/cookieSession.js'][49] = 0; + _$jscoverage['middleware/cookieSession.js'][52] = 0; + _$jscoverage['middleware/cookieSession.js'][55] = 0; + _$jscoverage['middleware/cookieSession.js'][56] = 0; + _$jscoverage['middleware/cookieSession.js'][59] = 0; + _$jscoverage['middleware/cookieSession.js'][60] = 0; + _$jscoverage['middleware/cookieSession.js'][63] = 0; + _$jscoverage['middleware/cookieSession.js'][66] = 0; + _$jscoverage['middleware/cookieSession.js'][67] = 0; + _$jscoverage['middleware/cookieSession.js'][70] = 0; + _$jscoverage['middleware/cookieSession.js'][71] = 0; + _$jscoverage['middleware/cookieSession.js'][72] = 0; + _$jscoverage['middleware/cookieSession.js'][73] = 0; + _$jscoverage['middleware/cookieSession.js'][74] = 0; + _$jscoverage['middleware/cookieSession.js'][75] = 0; + _$jscoverage['middleware/cookieSession.js'][80] = 0; + _$jscoverage['middleware/cookieSession.js'][82] = 0; + _$jscoverage['middleware/cookieSession.js'][83] = 0; + _$jscoverage['middleware/cookieSession.js'][84] = 0; + _$jscoverage['middleware/cookieSession.js'][85] = 0; + _$jscoverage['middleware/cookieSession.js'][86] = 0; + _$jscoverage['middleware/cookieSession.js'][89] = 0; + _$jscoverage['middleware/cookieSession.js'][92] = 0; + _$jscoverage['middleware/cookieSession.js'][97] = 0; + _$jscoverage['middleware/cookieSession.js'][100] = 0; + _$jscoverage['middleware/cookieSession.js'][101] = 0; + _$jscoverage['middleware/cookieSession.js'][104] = 0; + _$jscoverage['middleware/cookieSession.js'][107] = 0; + _$jscoverage['middleware/cookieSession.js'][108] = 0; + _$jscoverage['middleware/cookieSession.js'][109] = 0; + _$jscoverage['middleware/cookieSession.js'][110] = 0; + _$jscoverage['middleware/cookieSession.js'][113] = 0; +} +_$jscoverage['middleware/cookieSession.js'][12]++; +var utils = require("./../utils"), Cookie = require("./session/cookie"), debug = require("debug")("connect:cookieSession"), signature = require("cookie-signature"), crc16 = require("crc").crc16; +_$jscoverage['middleware/cookieSession.js'][46]++; +module.exports = (function cookieSession(options) { + _$jscoverage['middleware/cookieSession.js'][48]++; + options = options || {}; + _$jscoverage['middleware/cookieSession.js'][49]++; + var key = options.key || "connect.sess", trustProxy = options.proxy; + _$jscoverage['middleware/cookieSession.js'][52]++; + return (function cookieSession(req, res, next) { + _$jscoverage['middleware/cookieSession.js'][55]++; + var secret = options.secret || req.secret; + _$jscoverage['middleware/cookieSession.js'][56]++; + if (! secret) { + _$jscoverage['middleware/cookieSession.js'][56]++; + throw new Error("`secret` option required for cookie sessions"); + } + _$jscoverage['middleware/cookieSession.js'][59]++; + req.session = {}; + _$jscoverage['middleware/cookieSession.js'][60]++; + var cookie = req.session.cookie = new Cookie(options.cookie); + _$jscoverage['middleware/cookieSession.js'][63]++; + if (0 != req.originalUrl.indexOf(cookie.path)) { + _$jscoverage['middleware/cookieSession.js'][63]++; + return next(); + } + _$jscoverage['middleware/cookieSession.js'][66]++; + if (! options.secret && req.secret) { + _$jscoverage['middleware/cookieSession.js'][67]++; + req.session = req.signedCookies[key] || {}; + } + else { + _$jscoverage['middleware/cookieSession.js'][70]++; + var rawCookie = req.cookies[key]; + _$jscoverage['middleware/cookieSession.js'][71]++; + if (rawCookie) { + _$jscoverage['middleware/cookieSession.js'][72]++; + var unsigned = utils.parseSignedCookie(rawCookie, secret); + _$jscoverage['middleware/cookieSession.js'][73]++; + if (unsigned) { + _$jscoverage['middleware/cookieSession.js'][74]++; + var originalHash = crc16(unsigned); + _$jscoverage['middleware/cookieSession.js'][75]++; + req.session = utils.parseJSONCookie(unsigned) || {}; + } + } + } + _$jscoverage['middleware/cookieSession.js'][80]++; + res.on("header", (function () { + _$jscoverage['middleware/cookieSession.js'][82]++; + if (! req.session) { + _$jscoverage['middleware/cookieSession.js'][83]++; + debug("clear session"); + _$jscoverage['middleware/cookieSession.js'][84]++; + cookie.expires = new Date(0); + _$jscoverage['middleware/cookieSession.js'][85]++; + res.setHeader("Set-Cookie", cookie.serialize(key, "")); + _$jscoverage['middleware/cookieSession.js'][86]++; + return; + } + _$jscoverage['middleware/cookieSession.js'][89]++; + delete req.session.cookie; + _$jscoverage['middleware/cookieSession.js'][92]++; + var proto = (req.headers["x-forwarded-proto"] || "").toLowerCase(), tls = req.connection.encrypted || (trustProxy && "https" == proto), secured = cookie.secure && tls; + _$jscoverage['middleware/cookieSession.js'][97]++; + if (cookie.secure && ! secured) { + _$jscoverage['middleware/cookieSession.js'][97]++; + return debug("not secured"); + } + _$jscoverage['middleware/cookieSession.js'][100]++; + debug("serializing %j", req.session); + _$jscoverage['middleware/cookieSession.js'][101]++; + var val = "j:" + JSON.stringify(req.session); + _$jscoverage['middleware/cookieSession.js'][104]++; + if (originalHash == crc16(val)) { + _$jscoverage['middleware/cookieSession.js'][104]++; + return debug("unmodified session"); + } + _$jscoverage['middleware/cookieSession.js'][107]++; + val = "s:" + signature.sign(val, secret); + _$jscoverage['middleware/cookieSession.js'][108]++; + val = cookie.serialize(key, val); + _$jscoverage['middleware/cookieSession.js'][109]++; + debug("set-cookie %j", cookie); + _$jscoverage['middleware/cookieSession.js'][110]++; + res.setHeader("Set-Cookie", val); +})); + _$jscoverage['middleware/cookieSession.js'][113]++; + next(); +}); +}); +_$jscoverage['middleware/cookieSession.js'].source = ["","/*!"," * Connect - cookieSession"," * Copyright(c) 2011 Sencha Inc."," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('./../utils')"," , Cookie = require('./session/cookie')"," , debug = require('debug')('connect:cookieSession')"," , signature = require('cookie-signature')"," , crc16 = require('crc').crc16;","","/**"," * Cookie Session:"," *"," * Cookie session middleware."," *"," * var app = connect();"," * app.use(connect.cookieParser());"," * app.use(connect.cookieSession({ secret: 'tobo!', cookie: { maxAge: 60 * 60 * 1000 }}));"," *"," * Options:"," *"," * - `key` cookie name defaulting to `connect.sess`"," * - `secret` prevents cookie tampering"," * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }`"," * - `proxy` trust the reverse proxy when setting secure cookies (via \"x-forwarded-proto\")"," *"," * Clearing sessions:"," *"," * To clear the session simply set its value to `null`,"," * `cookieSession()` will then respond with a 1970 Set-Cookie."," *"," * req.session = null;"," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","module.exports = function cookieSession(options){"," // TODO: utilize Session/Cookie to unify API"," options = options || {};"," var key = options.key || 'connect.sess'"," , trustProxy = options.proxy;",""," return function cookieSession(req, res, next) {",""," // req.secret is for backwards compatibility"," var secret = options.secret || req.secret;"," if (!secret) throw new Error('`secret` option required for cookie sessions');",""," // default session"," req.session = {};"," var cookie = req.session.cookie = new Cookie(options.cookie);",""," // pathname mismatch"," if (0 != req.originalUrl.indexOf(cookie.path)) return next();",""," // cookieParser secret"," if (!options.secret && req.secret) {"," req.session = req.signedCookies[key] || {};"," } else {"," // TODO: refactor"," var rawCookie = req.cookies[key];"," if (rawCookie) {"," var unsigned = utils.parseSignedCookie(rawCookie, secret);"," if (unsigned) {"," var originalHash = crc16(unsigned);"," req.session = utils.parseJSONCookie(unsigned) || {};"," }"," }"," }",""," res.on('header', function(){"," // removed"," if (!req.session) {"," debug('clear session');"," cookie.expires = new Date(0);"," res.setHeader('Set-Cookie', cookie.serialize(key, ''));"," return;"," }",""," delete req.session.cookie;",""," // check security"," var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase()"," , tls = req.connection.encrypted || (trustProxy && 'https' == proto)"," , secured = cookie.secure && tls;",""," // only send secure cookies via https"," if (cookie.secure && !secured) return debug('not secured');",""," // serialize"," debug('serializing %j', req.session);"," var val = 'j:' + JSON.stringify(req.session);",""," // compare hashes, no need to set-cookie if unchanged"," if (originalHash == crc16(val)) return debug('unmodified session');",""," // set-cookie"," val = 's:' + signature.sign(val, secret);"," val = cookie.serialize(key, val);"," debug('set-cookie %j', cookie);"," res.setHeader('Set-Cookie', val);"," });",""," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/csrf.js b/node_modules/express/node_modules/connect/lib-cov/middleware/csrf.js new file mode 100644 index 0000000..f3919ed --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/csrf.js @@ -0,0 +1,51 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/csrf.js']) { + _$jscoverage['middleware/csrf.js'] = []; + _$jscoverage['middleware/csrf.js'][11] = 0; + _$jscoverage['middleware/csrf.js'][39] = 0; + _$jscoverage['middleware/csrf.js'][40] = 0; + _$jscoverage['middleware/csrf.js'][41] = 0; + _$jscoverage['middleware/csrf.js'][43] = 0; + _$jscoverage['middleware/csrf.js'][45] = 0; + _$jscoverage['middleware/csrf.js'][48] = 0; + _$jscoverage['middleware/csrf.js'][51] = 0; + _$jscoverage['middleware/csrf.js'][54] = 0; + _$jscoverage['middleware/csrf.js'][56] = 0; + _$jscoverage['middleware/csrf.js'][69] = 0; + _$jscoverage['middleware/csrf.js'][70] = 0; +} +_$jscoverage['middleware/csrf.js'][11]++; +var utils = require("../utils"); +_$jscoverage['middleware/csrf.js'][39]++; +module.exports = (function csrf(options) { + _$jscoverage['middleware/csrf.js'][40]++; + options = options || {}; + _$jscoverage['middleware/csrf.js'][41]++; + var value = options.value || defaultValue; + _$jscoverage['middleware/csrf.js'][43]++; + return (function (req, res, next) { + _$jscoverage['middleware/csrf.js'][45]++; + var token = req.session._csrf || (req.session._csrf = utils.uid(24)); + _$jscoverage['middleware/csrf.js'][48]++; + if ("GET" == req.method || "HEAD" == req.method || "OPTIONS" == req.method) { + _$jscoverage['middleware/csrf.js'][48]++; + return next(); + } + _$jscoverage['middleware/csrf.js'][51]++; + var val = value(req); + _$jscoverage['middleware/csrf.js'][54]++; + if (val != token) { + _$jscoverage['middleware/csrf.js'][54]++; + return next(utils.error(403)); + } + _$jscoverage['middleware/csrf.js'][56]++; + next(); +}); +}); +_$jscoverage['middleware/csrf.js'][69]++; +function defaultValue(req) { + _$jscoverage['middleware/csrf.js'][70]++; + return (req.body && req.body._csrf) || (req.query && req.query._csrf) || req.headers["x-csrf-token"]; +} +_$jscoverage['middleware/csrf.js'].source = ["/*!"," * Connect - csrf"," * Copyright(c) 2011 Sencha Inc."," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils');","","/**"," * Anti CSRF:"," *"," * CRSF protection middleware."," *"," * By default this middleware generates a token named \"_csrf\""," * which should be added to requests which mutate"," * state, within a hidden form field, query-string etc. This"," * token is validated against the visitor's `req.session._csrf`"," * property."," *"," * The default `value` function checks `req.body` generated"," * by the `bodyParser()` middleware, `req.query` generated"," * by `query()`, and the \"X-CSRF-Token\" header field."," *"," * This middleware requires session support, thus should be added"," * somewhere _below_ `session()` and `cookieParser()`."," *"," * Options:"," *"," * - `value` a function accepting the request, returning the token "," *"," * @param {Object} options"," * @api public"," */","","module.exports = function csrf(options) {"," options = options || {};"," var value = options.value || defaultValue;",""," return function(req, res, next){"," // generate CSRF token"," var token = req.session._csrf || (req.session._csrf = utils.uid(24));",""," // ignore these methods"," if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next();",""," // determine value"," var val = value(req);",""," // check"," if (val != token) return next(utils.error(403));"," "," next();"," }","};","","/**"," * Default value function, checking the `req.body`"," * and `req.query` for the CSRF token."," *"," * @param {IncomingMessage} req"," * @return {String}"," * @api private"," */","","function defaultValue(req) {"," return (req.body && req.body._csrf)"," || (req.query && req.query._csrf)"," || (req.headers['x-csrf-token']);","}"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/directory.js b/node_modules/express/node_modules/connect/lib-cov/middleware/directory.js new file mode 100644 index 0000000..bc86b60 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/directory.js @@ -0,0 +1,256 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/directory.js']) { + _$jscoverage['middleware/directory.js'] = []; + _$jscoverage['middleware/directory.js'][17] = 0; + _$jscoverage['middleware/directory.js'][29] = 0; + _$jscoverage['middleware/directory.js'][48] = 0; + _$jscoverage['middleware/directory.js'][49] = 0; + _$jscoverage['middleware/directory.js'][52] = 0; + _$jscoverage['middleware/directory.js'][53] = 0; + _$jscoverage['middleware/directory.js'][58] = 0; + _$jscoverage['middleware/directory.js'][59] = 0; + _$jscoverage['middleware/directory.js'][61] = 0; + _$jscoverage['middleware/directory.js'][70] = 0; + _$jscoverage['middleware/directory.js'][73] = 0; + _$jscoverage['middleware/directory.js'][76] = 0; + _$jscoverage['middleware/directory.js'][77] = 0; + _$jscoverage['middleware/directory.js'][81] = 0; + _$jscoverage['middleware/directory.js'][84] = 0; + _$jscoverage['middleware/directory.js'][85] = 0; + _$jscoverage['middleware/directory.js'][86] = 0; + _$jscoverage['middleware/directory.js'][87] = 0; + _$jscoverage['middleware/directory.js'][88] = 0; + _$jscoverage['middleware/directory.js'][91] = 0; + _$jscoverage['middleware/directory.js'][92] = 0; + _$jscoverage['middleware/directory.js'][93] = 0; + _$jscoverage['middleware/directory.js'][94] = 0; + _$jscoverage['middleware/directory.js'][99] = 0; + _$jscoverage['middleware/directory.js'][109] = 0; + _$jscoverage['middleware/directory.js'][110] = 0; + _$jscoverage['middleware/directory.js'][111] = 0; + _$jscoverage['middleware/directory.js'][112] = 0; + _$jscoverage['middleware/directory.js'][113] = 0; + _$jscoverage['middleware/directory.js'][114] = 0; + _$jscoverage['middleware/directory.js'][115] = 0; + _$jscoverage['middleware/directory.js'][120] = 0; + _$jscoverage['middleware/directory.js'][121] = 0; + _$jscoverage['middleware/directory.js'][122] = 0; + _$jscoverage['middleware/directory.js'][131] = 0; + _$jscoverage['middleware/directory.js'][132] = 0; + _$jscoverage['middleware/directory.js'][133] = 0; + _$jscoverage['middleware/directory.js'][134] = 0; + _$jscoverage['middleware/directory.js'][135] = 0; + _$jscoverage['middleware/directory.js'][142] = 0; + _$jscoverage['middleware/directory.js'][143] = 0; + _$jscoverage['middleware/directory.js'][144] = 0; + _$jscoverage['middleware/directory.js'][145] = 0; + _$jscoverage['middleware/directory.js'][146] = 0; + _$jscoverage['middleware/directory.js'][153] = 0; + _$jscoverage['middleware/directory.js'][154] = 0; + _$jscoverage['middleware/directory.js'][155] = 0; + _$jscoverage['middleware/directory.js'][156] = 0; + _$jscoverage['middleware/directory.js'][157] = 0; + _$jscoverage['middleware/directory.js'][165] = 0; + _$jscoverage['middleware/directory.js'][166] = 0; + _$jscoverage['middleware/directory.js'][167] = 0; + _$jscoverage['middleware/directory.js'][170] = 0; + _$jscoverage['middleware/directory.js'][171] = 0; + _$jscoverage['middleware/directory.js'][172] = 0; + _$jscoverage['middleware/directory.js'][173] = 0; + _$jscoverage['middleware/directory.js'][176] = 0; + _$jscoverage['middleware/directory.js'][194] = 0; + _$jscoverage['middleware/directory.js'][195] = 0; + _$jscoverage['middleware/directory.js'][196] = 0; + _$jscoverage['middleware/directory.js'][208] = 0; + _$jscoverage['middleware/directory.js'][209] = 0; + _$jscoverage['middleware/directory.js'][210] = 0; + _$jscoverage['middleware/directory.js'][218] = 0; +} +_$jscoverage['middleware/directory.js'][17]++; +var fs = require("fs"), parse = require("url").parse, utils = require("../utils"), path = require("path"), normalize = path.normalize, extname = path.extname, join = path.join; +_$jscoverage['middleware/directory.js'][29]++; +var cache = {}; +_$jscoverage['middleware/directory.js'][48]++; +exports = module.exports = (function directory(root, options) { + _$jscoverage['middleware/directory.js'][49]++; + options = options || {}; + _$jscoverage['middleware/directory.js'][52]++; + if (! root) { + _$jscoverage['middleware/directory.js'][52]++; + throw new Error("directory() root path required"); + } + _$jscoverage['middleware/directory.js'][53]++; + var hidden = options.hidden, icons = options.icons, filter = options.filter, root = normalize(root); + _$jscoverage['middleware/directory.js'][58]++; + return (function directory(req, res, next) { + _$jscoverage['middleware/directory.js'][59]++; + if ("GET" != req.method && "HEAD" != req.method) { + _$jscoverage['middleware/directory.js'][59]++; + return next(); + } + _$jscoverage['middleware/directory.js'][61]++; + var accept = req.headers.accept || "text/plain", url = parse(req.url), dir = decodeURIComponent(url.pathname), path = normalize(join(root, dir)), originalUrl = parse(req.originalUrl), originalDir = decodeURIComponent(originalUrl.pathname), showUp = path != root && path != root + "/"; + _$jscoverage['middleware/directory.js'][70]++; + if (~ path.indexOf("\u0000")) { + _$jscoverage['middleware/directory.js'][70]++; + return next(utils.error(400)); + } + _$jscoverage['middleware/directory.js'][73]++; + if (0 != path.indexOf(root)) { + _$jscoverage['middleware/directory.js'][73]++; + return next(utils.error(403)); + } + _$jscoverage['middleware/directory.js'][76]++; + fs.stat(path, (function (err, stat) { + _$jscoverage['middleware/directory.js'][77]++; + if (err) { + _$jscoverage['middleware/directory.js'][77]++; + return "ENOENT" == err.code? next(): next(err); + } + _$jscoverage['middleware/directory.js'][81]++; + if (! stat.isDirectory()) { + _$jscoverage['middleware/directory.js'][81]++; + return next(); + } + _$jscoverage['middleware/directory.js'][84]++; + fs.readdir(path, (function (err, files) { + _$jscoverage['middleware/directory.js'][85]++; + if (err) { + _$jscoverage['middleware/directory.js'][85]++; + return next(err); + } + _$jscoverage['middleware/directory.js'][86]++; + if (! hidden) { + _$jscoverage['middleware/directory.js'][86]++; + files = removeHidden(files); + } + _$jscoverage['middleware/directory.js'][87]++; + if (filter) { + _$jscoverage['middleware/directory.js'][87]++; + files = files.filter(filter); + } + _$jscoverage['middleware/directory.js'][88]++; + files.sort(); + _$jscoverage['middleware/directory.js'][91]++; + for (var key in exports) { + _$jscoverage['middleware/directory.js'][92]++; + if (~ accept.indexOf(key) || ~ accept.indexOf("*/*")) { + _$jscoverage['middleware/directory.js'][93]++; + exports[key](req, res, files, next, originalDir, showUp, icons); + _$jscoverage['middleware/directory.js'][94]++; + return; + } +} + _$jscoverage['middleware/directory.js'][99]++; + next(utils.error(406)); +})); +})); +}); +}); +_$jscoverage['middleware/directory.js'][109]++; +exports.html = (function (req, res, files, next, dir, showUp, icons) { + _$jscoverage['middleware/directory.js'][110]++; + fs.readFile(__dirname + "/../public/directory.html", "utf8", (function (err, str) { + _$jscoverage['middleware/directory.js'][111]++; + if (err) { + _$jscoverage['middleware/directory.js'][111]++; + return next(err); + } + _$jscoverage['middleware/directory.js'][112]++; + fs.readFile(__dirname + "/../public/style.css", "utf8", (function (err, style) { + _$jscoverage['middleware/directory.js'][113]++; + if (err) { + _$jscoverage['middleware/directory.js'][113]++; + return next(err); + } + _$jscoverage['middleware/directory.js'][114]++; + if (showUp) { + _$jscoverage['middleware/directory.js'][114]++; + files.unshift(".."); + } + _$jscoverage['middleware/directory.js'][115]++; + str = str.replace("{style}", style).replace("{files}", html(files, dir, icons)).replace("{directory}", dir).replace("{linked-path}", htmlPath(dir)); + _$jscoverage['middleware/directory.js'][120]++; + res.setHeader("Content-Type", "text/html"); + _$jscoverage['middleware/directory.js'][121]++; + res.setHeader("Content-Length", str.length); + _$jscoverage['middleware/directory.js'][122]++; + res.end(str); +})); +})); +}); +_$jscoverage['middleware/directory.js'][131]++; +exports.json = (function (req, res, files) { + _$jscoverage['middleware/directory.js'][132]++; + files = JSON.stringify(files); + _$jscoverage['middleware/directory.js'][133]++; + res.setHeader("Content-Type", "application/json"); + _$jscoverage['middleware/directory.js'][134]++; + res.setHeader("Content-Length", files.length); + _$jscoverage['middleware/directory.js'][135]++; + res.end(files); +}); +_$jscoverage['middleware/directory.js'][142]++; +exports.plain = (function (req, res, files) { + _$jscoverage['middleware/directory.js'][143]++; + files = files.join("\n") + "\n"; + _$jscoverage['middleware/directory.js'][144]++; + res.setHeader("Content-Type", "text/plain"); + _$jscoverage['middleware/directory.js'][145]++; + res.setHeader("Content-Length", files.length); + _$jscoverage['middleware/directory.js'][146]++; + res.end(files); +}); +_$jscoverage['middleware/directory.js'][153]++; +function htmlPath(dir) { + _$jscoverage['middleware/directory.js'][154]++; + var curr = []; + _$jscoverage['middleware/directory.js'][155]++; + return dir.split("/").map((function (part) { + _$jscoverage['middleware/directory.js'][156]++; + curr.push(part); + _$jscoverage['middleware/directory.js'][157]++; + return "" + part + ""; +})).join(" / "); +} +_$jscoverage['middleware/directory.js'][165]++; +function html(files, dir, useIcons) { + _$jscoverage['middleware/directory.js'][166]++; + return "
    " + files.map((function (file) { + _$jscoverage['middleware/directory.js'][167]++; + var icon = "", classes = []; + _$jscoverage['middleware/directory.js'][170]++; + if (useIcons && ".." != file) { + _$jscoverage['middleware/directory.js'][171]++; + icon = icons[extname(file)] || icons["default"]; + _$jscoverage['middleware/directory.js'][172]++; + icon = ""; + _$jscoverage['middleware/directory.js'][173]++; + classes.push("icon"); + } + _$jscoverage['middleware/directory.js'][176]++; + return "
  • " + icon + file + "
  • "; +})).join("\n") + "
"; +} +_$jscoverage['middleware/directory.js'][194]++; +function load(icon) { + _$jscoverage['middleware/directory.js'][195]++; + if (cache[icon]) { + _$jscoverage['middleware/directory.js'][195]++; + return cache[icon]; + } + _$jscoverage['middleware/directory.js'][196]++; + return cache[icon] = fs.readFileSync(__dirname + "/../public/icons/" + icon, "base64"); +} +_$jscoverage['middleware/directory.js'][208]++; +function removeHidden(files) { + _$jscoverage['middleware/directory.js'][209]++; + return files.filter((function (file) { + _$jscoverage['middleware/directory.js'][210]++; + return "." != file[0]; +})); +} +_$jscoverage['middleware/directory.js'][218]++; +var icons = {".js": "page_white_code_red.png", ".c": "page_white_c.png", ".h": "page_white_h.png", ".cc": "page_white_cplusplus.png", ".php": "page_white_php.png", ".rb": "page_white_ruby.png", ".cpp": "page_white_cplusplus.png", ".swf": "page_white_flash.png", ".pdf": "page_white_acrobat.png", "default": "page_white.png"}; +_$jscoverage['middleware/directory.js'].source = ["","/*!"," * Connect - directory"," * Copyright(c) 2011 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","// TODO: icon / style for directories","// TODO: arrow key navigation","// TODO: make icons extensible","","/**"," * Module dependencies."," */","","var fs = require('fs')"," , parse = require('url').parse"," , utils = require('../utils')"," , path = require('path')"," , normalize = path.normalize"," , extname = path.extname"," , join = path.join;","","/*!"," * Icon cache."," */","","var cache = {};","","/**"," * Directory:"," *"," * Serve directory listings with the given `root` path."," *"," * Options:"," *"," * - `hidden` display hidden (dot) files. Defaults to false."," * - `icons` display icons. Defaults to false."," * - `filter` Apply this filter function to files. Defaults to false."," *"," * @param {String} root"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function directory(root, options){"," options = options || {};",""," // root required"," if (!root) throw new Error('directory() root path required');"," var hidden = options.hidden"," , icons = options.icons"," , filter = options.filter"," , root = normalize(root);",""," return function directory(req, res, next) {"," if ('GET' != req.method && 'HEAD' != req.method) return next();",""," var accept = req.headers.accept || 'text/plain'"," , url = parse(req.url)"," , dir = decodeURIComponent(url.pathname)"," , path = normalize(join(root, dir))"," , originalUrl = parse(req.originalUrl)"," , originalDir = decodeURIComponent(originalUrl.pathname)"," , showUp = path != root && path != root + '/';",""," // null byte(s), bad request"," if (~path.indexOf('\\0')) return next(utils.error(400));",""," // malicious path, forbidden"," if (0 != path.indexOf(root)) return next(utils.error(403));",""," // check if we have a directory"," fs.stat(path, function(err, stat){"," if (err) return 'ENOENT' == err.code"," ? next()"," : next(err);",""," if (!stat.isDirectory()) return next();",""," // fetch files"," fs.readdir(path, function(err, files){"," if (err) return next(err);"," if (!hidden) files = removeHidden(files);"," if (filter) files = files.filter(filter);"," files.sort();",""," // content-negotiation"," for (var key in exports) {"," if (~accept.indexOf(key) || ~accept.indexOf('*/*')) {"," exports[key](req, res, files, next, originalDir, showUp, icons);"," return;"," }"," }",""," // not acceptable"," next(utils.error(406));"," });"," });"," };","};","","/**"," * Respond with text/html."," */","","exports.html = function(req, res, files, next, dir, showUp, icons){"," fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){"," if (err) return next(err);"," fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){"," if (err) return next(err);"," if (showUp) files.unshift('..');"," str = str"," .replace('{style}', style)"," .replace('{files}', html(files, dir, icons))"," .replace('{directory}', dir)"," .replace('{linked-path}', htmlPath(dir));"," res.setHeader('Content-Type', 'text/html');"," res.setHeader('Content-Length', str.length);"," res.end(str);"," });"," });","};","","/**"," * Respond with application/json."," */","","exports.json = function(req, res, files){"," files = JSON.stringify(files);"," res.setHeader('Content-Type', 'application/json');"," res.setHeader('Content-Length', files.length);"," res.end(files);","};","","/**"," * Respond with text/plain."," */","","exports.plain = function(req, res, files){"," files = files.join('\\n') + '\\n';"," res.setHeader('Content-Type', 'text/plain');"," res.setHeader('Content-Length', files.length);"," res.end(files);","};","","/**"," * Map html `dir`, returning a linked path."," */","","function htmlPath(dir) {"," var curr = [];"," return dir.split('/').map(function(part){"," curr.push(part);"," return '<a href=\"' + curr.join('/') + '\">' + part + '</a>';"," }).join(' / ');","}","","/**"," * Map html `files`, returning an html unordered list."," */","","function html(files, dir, useIcons) {"," return '<ul id=\"files\">' + files.map(function(file){"," var icon = ''"," , classes = [];",""," if (useIcons && '..' != file) {"," icon = icons[extname(file)] || icons.default;"," icon = '<img src=\"data:image/png;base64,' + load(icon) + '\" />';"," classes.push('icon');"," }",""," return '<li><a href=\"'"," + join(dir, file)"," + '\" class=\"'"," + classes.join(' ') + '\"'"," + ' title=\"' + file + '\">'"," + icon + file + '</a></li>';",""," }).join('\\n') + '</ul>';","}","","/**"," * Load and cache the given `icon`."," *"," * @param {String} icon"," * @return {String}"," * @api private"," */","","function load(icon) {"," if (cache[icon]) return cache[icon];"," return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64');","}","","/**"," * Filter \"hidden\" `files`, aka files"," * beginning with a `.`."," *"," * @param {Array} files"," * @return {Array}"," * @api private"," */","","function removeHidden(files) {"," return files.filter(function(file){"," return '.' != file[0];"," });","}","","/**"," * Icon map."," */","","var icons = {"," '.js': 'page_white_code_red.png'"," , '.c': 'page_white_c.png'"," , '.h': 'page_white_h.png'"," , '.cc': 'page_white_cplusplus.png'"," , '.php': 'page_white_php.png'"," , '.rb': 'page_white_ruby.png'"," , '.cpp': 'page_white_cplusplus.png'"," , '.swf': 'page_white_flash.png'"," , '.pdf': 'page_white_acrobat.png'"," , 'default': 'page_white.png'","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/errorHandler.js b/node_modules/express/node_modules/connect/lib-cov/middleware/errorHandler.js new file mode 100644 index 0000000..9a87bfa --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/errorHandler.js @@ -0,0 +1,104 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/errorHandler.js']) { + _$jscoverage['middleware/errorHandler.js'] = []; + _$jscoverage['middleware/errorHandler.js'][12] = 0; + _$jscoverage['middleware/errorHandler.js'][17] = 0; + _$jscoverage['middleware/errorHandler.js'][44] = 0; + _$jscoverage['middleware/errorHandler.js'][45] = 0; + _$jscoverage['middleware/errorHandler.js'][46] = 0; + _$jscoverage['middleware/errorHandler.js'][47] = 0; + _$jscoverage['middleware/errorHandler.js'][48] = 0; + _$jscoverage['middleware/errorHandler.js'][49] = 0; + _$jscoverage['middleware/errorHandler.js'][51] = 0; + _$jscoverage['middleware/errorHandler.js'][52] = 0; + _$jscoverage['middleware/errorHandler.js'][53] = 0; + _$jscoverage['middleware/errorHandler.js'][54] = 0; + _$jscoverage['middleware/errorHandler.js'][56] = 0; + _$jscoverage['middleware/errorHandler.js'][57] = 0; + _$jscoverage['middleware/errorHandler.js'][63] = 0; + _$jscoverage['middleware/errorHandler.js'][64] = 0; + _$jscoverage['middleware/errorHandler.js'][68] = 0; + _$jscoverage['middleware/errorHandler.js'][69] = 0; + _$jscoverage['middleware/errorHandler.js'][70] = 0; + _$jscoverage['middleware/errorHandler.js'][71] = 0; + _$jscoverage['middleware/errorHandler.js'][72] = 0; + _$jscoverage['middleware/errorHandler.js'][73] = 0; + _$jscoverage['middleware/errorHandler.js'][76] = 0; + _$jscoverage['middleware/errorHandler.js'][77] = 0; + _$jscoverage['middleware/errorHandler.js'][86] = 0; +} +_$jscoverage['middleware/errorHandler.js'][12]++; +var utils = require("../utils"), fs = require("fs"); +_$jscoverage['middleware/errorHandler.js'][17]++; +var env = process.env.NODE_ENV || "development"; +_$jscoverage['middleware/errorHandler.js'][44]++; +exports = module.exports = (function errorHandler() { + _$jscoverage['middleware/errorHandler.js'][45]++; + return (function errorHandler(err, req, res, next) { + _$jscoverage['middleware/errorHandler.js'][46]++; + if (err.status) { + _$jscoverage['middleware/errorHandler.js'][46]++; + res.statusCode = err.status; + } + _$jscoverage['middleware/errorHandler.js'][47]++; + if (res.statusCode < 400) { + _$jscoverage['middleware/errorHandler.js'][47]++; + res.statusCode = 500; + } + _$jscoverage['middleware/errorHandler.js'][48]++; + if ("test" != env) { + _$jscoverage['middleware/errorHandler.js'][48]++; + console.error(err.stack); + } + _$jscoverage['middleware/errorHandler.js'][49]++; + var accept = req.headers.accept || ""; + _$jscoverage['middleware/errorHandler.js'][51]++; + if (~ accept.indexOf("html")) { + _$jscoverage['middleware/errorHandler.js'][52]++; + fs.readFile(__dirname + "/../public/style.css", "utf8", (function (e, style) { + _$jscoverage['middleware/errorHandler.js'][53]++; + fs.readFile(__dirname + "/../public/error.html", "utf8", (function (e, html) { + _$jscoverage['middleware/errorHandler.js'][54]++; + var stack = (err.stack || "").split("\n").slice(1).map((function (v) { + _$jscoverage['middleware/errorHandler.js'][56]++; + return "
  • " + v + "
  • "; +})).join(""); + _$jscoverage['middleware/errorHandler.js'][57]++; + html = html.replace("{style}", style).replace("{stack}", stack).replace("{title}", exports.title).replace("{statusCode}", res.statusCode).replace(/\{error\}/g, utils.escape(err.toString())); + _$jscoverage['middleware/errorHandler.js'][63]++; + res.setHeader("Content-Type", "text/html; charset=utf-8"); + _$jscoverage['middleware/errorHandler.js'][64]++; + res.end(html); +})); +})); + } + else { + _$jscoverage['middleware/errorHandler.js'][68]++; + if (~ accept.indexOf("json")) { + _$jscoverage['middleware/errorHandler.js'][69]++; + var error = {message: err.message, stack: err.stack}; + _$jscoverage['middleware/errorHandler.js'][70]++; + for (var prop in err) { + _$jscoverage['middleware/errorHandler.js'][70]++; + error[prop] = err[prop]; +} + _$jscoverage['middleware/errorHandler.js'][71]++; + var json = JSON.stringify({error: error}); + _$jscoverage['middleware/errorHandler.js'][72]++; + res.setHeader("Content-Type", "application/json"); + _$jscoverage['middleware/errorHandler.js'][73]++; + res.end(json); + } + else { + _$jscoverage['middleware/errorHandler.js'][76]++; + res.writeHead(res.statusCode, {"Content-Type": "text/plain"}); + _$jscoverage['middleware/errorHandler.js'][77]++; + res.end(err.stack); + } + } +}); +}); +_$jscoverage['middleware/errorHandler.js'][86]++; +exports.title = "Connect"; +_$jscoverage['middleware/errorHandler.js'].source = ["/*!"," * Connect - errorHandler"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils')"," , fs = require('fs');","","// environment","","var env = process.env.NODE_ENV || 'development';","","/**"," * Error handler:"," *"," * Development error handler, providing stack traces"," * and error message responses for requests accepting text, html,"," * or json."," *"," * Text:"," *"," * By default, and when _text/plain_ is accepted a simple stack trace"," * or error message will be returned."," *"," * JSON:"," *"," * When _application/json_ is accepted, connect will respond with"," * an object in the form of `{ \"error\": error }`."," *"," * HTML:"," *"," * When accepted connect will output a nice html stack trace."," *"," * @return {Function}"," * @api public"," */","","exports = module.exports = function errorHandler(){"," return function errorHandler(err, req, res, next){"," if (err.status) res.statusCode = err.status;"," if (res.statusCode < 400) res.statusCode = 500;"," if ('test' != env) console.error(err.stack);"," var accept = req.headers.accept || '';"," // html"," if (~accept.indexOf('html')) {"," fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){"," fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){"," var stack = (err.stack || '')"," .split('\\n').slice(1)"," .map(function(v){ return '<li>' + v + '</li>'; }).join('');"," html = html"," .replace('{style}', style)"," .replace('{stack}', stack)"," .replace('{title}', exports.title)"," .replace('{statusCode}', res.statusCode)"," .replace(/\\{error\\}/g, utils.escape(err.toString()));"," res.setHeader('Content-Type', 'text/html; charset=utf-8');"," res.end(html);"," });"," });"," // json"," } else if (~accept.indexOf('json')) {"," var error = { message: err.message, stack: err.stack };"," for (var prop in err) error[prop] = err[prop];"," var json = JSON.stringify({ error: error });"," res.setHeader('Content-Type', 'application/json');"," res.end(json);"," // plain text"," } else {"," res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });"," res.end(err.stack);"," }"," };","};","","/**"," * Template title, framework authors may override this value."," */","","exports.title = 'Connect';"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/favicon.js b/node_modules/express/node_modules/connect/lib-cov/middleware/favicon.js new file mode 100644 index 0000000..6228079 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/favicon.js @@ -0,0 +1,60 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/favicon.js']) { + _$jscoverage['middleware/favicon.js'] = []; + _$jscoverage['middleware/favicon.js'][13] = 0; + _$jscoverage['middleware/favicon.js'][50] = 0; + _$jscoverage['middleware/favicon.js'][51] = 0; + _$jscoverage['middleware/favicon.js'][56] = 0; + _$jscoverage['middleware/favicon.js'][57] = 0; + _$jscoverage['middleware/favicon.js'][58] = 0; + _$jscoverage['middleware/favicon.js'][59] = 0; + _$jscoverage['middleware/favicon.js'][60] = 0; + _$jscoverage['middleware/favicon.js'][62] = 0; + _$jscoverage['middleware/favicon.js'][63] = 0; + _$jscoverage['middleware/favicon.js'][64] = 0; + _$jscoverage['middleware/favicon.js'][73] = 0; + _$jscoverage['middleware/favicon.js'][74] = 0; + _$jscoverage['middleware/favicon.js'][78] = 0; +} +_$jscoverage['middleware/favicon.js'][13]++; +var fs = require("fs"), utils = require("../utils"); +_$jscoverage['middleware/favicon.js'][50]++; +module.exports = (function favicon(path, options) { + _$jscoverage['middleware/favicon.js'][51]++; + var options = options || {}, path = path || __dirname + "/../public/favicon.ico", maxAge = options.maxAge || 86400000, icon; + _$jscoverage['middleware/favicon.js'][56]++; + return (function favicon(req, res, next) { + _$jscoverage['middleware/favicon.js'][57]++; + if ("/favicon.ico" == req.url) { + _$jscoverage['middleware/favicon.js'][58]++; + if (icon) { + _$jscoverage['middleware/favicon.js'][59]++; + res.writeHead(200, icon.headers); + _$jscoverage['middleware/favicon.js'][60]++; + res.end(icon.body); + } + else { + _$jscoverage['middleware/favicon.js'][62]++; + fs.readFile(path, (function (err, buf) { + _$jscoverage['middleware/favicon.js'][63]++; + if (err) { + _$jscoverage['middleware/favicon.js'][63]++; + return next(err); + } + _$jscoverage['middleware/favicon.js'][64]++; + icon = {headers: {"Content-Type": "image/x-icon", "Content-Length": buf.length, "ETag": "\"" + utils.md5(buf) + "\"", "Cache-Control": "public, max-age=" + (maxAge / 1000)}, body: buf}; + _$jscoverage['middleware/favicon.js'][73]++; + res.writeHead(200, icon.headers); + _$jscoverage['middleware/favicon.js'][74]++; + res.end(icon.body); +})); + } + } + else { + _$jscoverage['middleware/favicon.js'][78]++; + next(); + } +}); +}); +_$jscoverage['middleware/favicon.js'].source = ["","/*!"," * Connect - favicon"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var fs = require('fs')"," , utils = require('../utils');","","/**"," * Favicon:"," *"," * By default serves the connect favicon, or the favicon"," * located by the given `path`."," *"," * Options:"," *"," * - `maxAge` cache-control max-age directive, defaulting to 1 day"," *"," * Examples:"," *"," * Serve default favicon:"," *"," * connect()"," * .use(connect.favicon())"," *"," * Serve favicon before logging for brevity:"," *"," * connect()"," * .use(connect.favicon())"," * .use(connect.logger('dev'))"," *"," * Serve custom favicon:"," *"," * connect()"," * .use(connect.favicon('public/favicon.ico))"," *"," * @param {String} path"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","module.exports = function favicon(path, options){"," var options = options || {}"," , path = path || __dirname + '/../public/favicon.ico'"," , maxAge = options.maxAge || 86400000"," , icon; // favicon cache",""," return function favicon(req, res, next){"," if ('/favicon.ico' == req.url) {"," if (icon) {"," res.writeHead(200, icon.headers);"," res.end(icon.body);"," } else {"," fs.readFile(path, function(err, buf){"," if (err) return next(err);"," icon = {"," headers: {"," 'Content-Type': 'image/x-icon'"," , 'Content-Length': buf.length"," , 'ETag': '\"' + utils.md5(buf) + '\"'"," , 'Cache-Control': 'public, max-age=' + (maxAge / 1000)"," },"," body: buf"," };"," res.writeHead(200, icon.headers);"," res.end(icon.body);"," });"," }"," } else {"," next();"," }"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/json.js b/node_modules/express/node_modules/connect/lib-cov/middleware/json.js new file mode 100644 index 0000000..87236cf --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/json.js @@ -0,0 +1,117 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/json.js']) { + _$jscoverage['middleware/json.js'] = []; + _$jscoverage['middleware/json.js'][13] = 0; + _$jscoverage['middleware/json.js'][20] = 0; + _$jscoverage['middleware/json.js'][21] = 0; + _$jscoverage['middleware/json.js'][41] = 0; + _$jscoverage['middleware/json.js'][42] = 0; + _$jscoverage['middleware/json.js'][45] = 0; + _$jscoverage['middleware/json.js'][49] = 0; + _$jscoverage['middleware/json.js'][50] = 0; + _$jscoverage['middleware/json.js'][51] = 0; + _$jscoverage['middleware/json.js'][53] = 0; + _$jscoverage['middleware/json.js'][56] = 0; + _$jscoverage['middleware/json.js'][59] = 0; + _$jscoverage['middleware/json.js'][62] = 0; + _$jscoverage['middleware/json.js'][63] = 0; + _$jscoverage['middleware/json.js'][64] = 0; + _$jscoverage['middleware/json.js'][65] = 0; + _$jscoverage['middleware/json.js'][66] = 0; + _$jscoverage['middleware/json.js'][67] = 0; + _$jscoverage['middleware/json.js'][68] = 0; + _$jscoverage['middleware/json.js'][70] = 0; + _$jscoverage['middleware/json.js'][71] = 0; + _$jscoverage['middleware/json.js'][74] = 0; + _$jscoverage['middleware/json.js'][75] = 0; + _$jscoverage['middleware/json.js'][76] = 0; + _$jscoverage['middleware/json.js'][77] = 0; + _$jscoverage['middleware/json.js'][79] = 0; + _$jscoverage['middleware/json.js'][80] = 0; + _$jscoverage['middleware/json.js'][81] = 0; +} +_$jscoverage['middleware/json.js'][13]++; +var utils = require("../utils"), _limit = require("./limit"); +_$jscoverage['middleware/json.js'][20]++; +function noop(req, res, next) { + _$jscoverage['middleware/json.js'][21]++; + next(); +} +_$jscoverage['middleware/json.js'][41]++; +exports = module.exports = (function (options) { + _$jscoverage['middleware/json.js'][42]++; + var options = options || {}, strict = options.strict !== false; + _$jscoverage['middleware/json.js'][45]++; + var limit = options.limit? _limit(options.limit): noop; + _$jscoverage['middleware/json.js'][49]++; + return (function json(req, res, next) { + _$jscoverage['middleware/json.js'][50]++; + if (req._body) { + _$jscoverage['middleware/json.js'][50]++; + return next(); + } + _$jscoverage['middleware/json.js'][51]++; + req.body = req.body || {}; + _$jscoverage['middleware/json.js'][53]++; + if (! utils.hasBody(req)) { + _$jscoverage['middleware/json.js'][53]++; + return next(); + } + _$jscoverage['middleware/json.js'][56]++; + if ("application/json" != utils.mime(req)) { + _$jscoverage['middleware/json.js'][56]++; + return next(); + } + _$jscoverage['middleware/json.js'][59]++; + req._body = true; + _$jscoverage['middleware/json.js'][62]++; + limit(req, res, (function (err) { + _$jscoverage['middleware/json.js'][63]++; + if (err) { + _$jscoverage['middleware/json.js'][63]++; + return next(err); + } + _$jscoverage['middleware/json.js'][64]++; + var buf = ""; + _$jscoverage['middleware/json.js'][65]++; + req.setEncoding("utf8"); + _$jscoverage['middleware/json.js'][66]++; + req.on("data", (function (chunk) { + _$jscoverage['middleware/json.js'][66]++; + buf += chunk; +})); + _$jscoverage['middleware/json.js'][67]++; + req.on("end", (function () { + _$jscoverage['middleware/json.js'][68]++; + var first = buf.trim()[0]; + _$jscoverage['middleware/json.js'][70]++; + if (0 == buf.length) { + _$jscoverage['middleware/json.js'][71]++; + return next(utils.error(400, "invalid json, empty body")); + } + _$jscoverage['middleware/json.js'][74]++; + if (strict && "{" != first && "[" != first) { + _$jscoverage['middleware/json.js'][74]++; + return next(utils.error(400, "invalid json")); + } + _$jscoverage['middleware/json.js'][75]++; + try { + _$jscoverage['middleware/json.js'][76]++; + req.body = JSON.parse(buf, options.reviver); + _$jscoverage['middleware/json.js'][77]++; + next(); + } + catch (err) { + _$jscoverage['middleware/json.js'][79]++; + err.body = buf; + _$jscoverage['middleware/json.js'][80]++; + err.status = 400; + _$jscoverage['middleware/json.js'][81]++; + next(err); + } +})); +})); +}); +}); +_$jscoverage['middleware/json.js'].source = ["","/*!"," * Connect - json"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils')"," , _limit = require('./limit');","","/**"," * noop middleware."," */","","function noop(req, res, next) {"," next();","}","","/**"," * JSON:"," *"," * Parse JSON request bodies, providing the"," * parsed object as `req.body`."," *"," * Options:"," *"," * - `strict` when `false` anything `JSON.parse()` accepts will be parsed"," * - `reviver` used as the second \"reviver\" argument for JSON.parse"," * - `limit` byte limit disabled by default"," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function(options){"," var options = options || {}"," , strict = options.strict !== false;",""," var limit = options.limit"," ? _limit(options.limit)"," : noop;",""," return function json(req, res, next) {"," if (req._body) return next();"," req.body = req.body || {};",""," if (!utils.hasBody(req)) return next();",""," // check Content-Type"," if ('application/json' != utils.mime(req)) return next();",""," // flag as parsed"," req._body = true;",""," // parse"," limit(req, res, function(err){"," if (err) return next(err);"," var buf = '';"," req.setEncoding('utf8');"," req.on('data', function(chunk){ buf += chunk });"," req.on('end', function(){"," var first = buf.trim()[0];",""," if (0 == buf.length) {"," return next(utils.error(400, 'invalid json, empty body'));"," }"," "," if (strict && '{' != first && '[' != first) return next(utils.error(400, 'invalid json'));"," try {"," req.body = JSON.parse(buf, options.reviver);"," next();"," } catch (err){"," err.body = buf;"," err.status = 400;"," next(err);"," }"," });"," });"," }","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/limit.js b/node_modules/express/node_modules/connect/lib-cov/middleware/limit.js new file mode 100644 index 0000000..fa8ea34 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/limit.js @@ -0,0 +1,63 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/limit.js']) { + _$jscoverage['middleware/limit.js'] = []; + _$jscoverage['middleware/limit.js'][12] = 0; + _$jscoverage['middleware/limit.js'][31] = 0; + _$jscoverage['middleware/limit.js'][32] = 0; + _$jscoverage['middleware/limit.js'][33] = 0; + _$jscoverage['middleware/limit.js'][34] = 0; + _$jscoverage['middleware/limit.js'][35] = 0; + _$jscoverage['middleware/limit.js'][41] = 0; + _$jscoverage['middleware/limit.js'][42] = 0; + _$jscoverage['middleware/limit.js'][45] = 0; + _$jscoverage['middleware/limit.js'][48] = 0; + _$jscoverage['middleware/limit.js'][49] = 0; + _$jscoverage['middleware/limit.js'][50] = 0; + _$jscoverage['middleware/limit.js'][53] = 0; +} +_$jscoverage['middleware/limit.js'][12]++; +var utils = require("../utils"); +_$jscoverage['middleware/limit.js'][31]++; +module.exports = (function limit(bytes) { + _$jscoverage['middleware/limit.js'][32]++; + if ("string" == typeof bytes) { + _$jscoverage['middleware/limit.js'][32]++; + bytes = utils.parseBytes(bytes); + } + _$jscoverage['middleware/limit.js'][33]++; + if ("number" != typeof bytes) { + _$jscoverage['middleware/limit.js'][33]++; + throw new Error("limit() bytes required"); + } + _$jscoverage['middleware/limit.js'][34]++; + return (function limit(req, res, next) { + _$jscoverage['middleware/limit.js'][35]++; + var received = 0, len = req.headers["content-length"]? parseInt(req.headers["content-length"], 10): null; + _$jscoverage['middleware/limit.js'][41]++; + if (req._limit) { + _$jscoverage['middleware/limit.js'][41]++; + return next(); + } + _$jscoverage['middleware/limit.js'][42]++; + req._limit = true; + _$jscoverage['middleware/limit.js'][45]++; + if (len && len > bytes) { + _$jscoverage['middleware/limit.js'][45]++; + return next(utils.error(413)); + } + _$jscoverage['middleware/limit.js'][48]++; + req.on("data", (function (chunk) { + _$jscoverage['middleware/limit.js'][49]++; + received += chunk.length; + _$jscoverage['middleware/limit.js'][50]++; + if (received > bytes) { + _$jscoverage['middleware/limit.js'][50]++; + req.destroy(); + } +})); + _$jscoverage['middleware/limit.js'][53]++; + next(); +}); +}); +_$jscoverage['middleware/limit.js'].source = ["","/*!"," * Connect - limit"," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils');","","/**"," * Limit:"," *"," * Limit request bodies to the given size in `bytes`."," *"," * A string representation of the bytesize may also be passed,"," * for example \"5mb\", \"200kb\", \"1gb\", etc."," *"," * connect()"," * .use(connect.limit('5.5mb'))"," * .use(handleImageUpload)"," *"," * @param {Number|String} bytes"," * @return {Function}"," * @api public"," */","","module.exports = function limit(bytes){"," if ('string' == typeof bytes) bytes = utils.parseBytes(bytes);"," if ('number' != typeof bytes) throw new Error('limit() bytes required');"," return function limit(req, res, next){"," var received = 0"," , len = req.headers['content-length']"," ? parseInt(req.headers['content-length'], 10)"," : null;",""," // self-awareness"," if (req._limit) return next();"," req._limit = true;",""," // limit by content-length"," if (len && len > bytes) return next(utils.error(413));",""," // limit"," req.on('data', function(chunk){"," received += chunk.length;"," if (received > bytes) req.destroy();"," });",""," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/logger.js b/node_modules/express/node_modules/connect/lib-cov/middleware/logger.js new file mode 100644 index 0000000..75c7a00 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/logger.js @@ -0,0 +1,312 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/logger.js']) { + _$jscoverage['middleware/logger.js'] = []; + _$jscoverage['middleware/logger.js'][12] = 0; + _$jscoverage['middleware/logger.js'][18] = 0; + _$jscoverage['middleware/logger.js'][24] = 0; + _$jscoverage['middleware/logger.js'][90] = 0; + _$jscoverage['middleware/logger.js'][91] = 0; + _$jscoverage['middleware/logger.js'][92] = 0; + _$jscoverage['middleware/logger.js'][93] = 0; + _$jscoverage['middleware/logger.js'][94] = 0; + _$jscoverage['middleware/logger.js'][96] = 0; + _$jscoverage['middleware/logger.js'][100] = 0; + _$jscoverage['middleware/logger.js'][103] = 0; + _$jscoverage['middleware/logger.js'][106] = 0; + _$jscoverage['middleware/logger.js'][109] = 0; + _$jscoverage['middleware/logger.js'][113] = 0; + _$jscoverage['middleware/logger.js'][114] = 0; + _$jscoverage['middleware/logger.js'][120] = 0; + _$jscoverage['middleware/logger.js'][121] = 0; + _$jscoverage['middleware/logger.js'][122] = 0; + _$jscoverage['middleware/logger.js'][123] = 0; + _$jscoverage['middleware/logger.js'][128] = 0; + _$jscoverage['middleware/logger.js'][130] = 0; + _$jscoverage['middleware/logger.js'][135] = 0; + _$jscoverage['middleware/logger.js'][136] = 0; + _$jscoverage['middleware/logger.js'][139] = 0; + _$jscoverage['middleware/logger.js'][140] = 0; + _$jscoverage['middleware/logger.js'][141] = 0; + _$jscoverage['middleware/logger.js'][142] = 0; + _$jscoverage['middleware/logger.js'][145] = 0; + _$jscoverage['middleware/logger.js'][146] = 0; + _$jscoverage['middleware/logger.js'][147] = 0; + _$jscoverage['middleware/logger.js'][148] = 0; + _$jscoverage['middleware/logger.js'][149] = 0; + _$jscoverage['middleware/logger.js'][150] = 0; + _$jscoverage['middleware/logger.js'][151] = 0; + _$jscoverage['middleware/logger.js'][156] = 0; + _$jscoverage['middleware/logger.js'][168] = 0; + _$jscoverage['middleware/logger.js'][169] = 0; + _$jscoverage['middleware/logger.js'][170] = 0; + _$jscoverage['middleware/logger.js'][171] = 0; + _$jscoverage['middleware/logger.js'][173] = 0; + _$jscoverage['middleware/logger.js'][174] = 0; + _$jscoverage['middleware/logger.js'][186] = 0; + _$jscoverage['middleware/logger.js'][187] = 0; + _$jscoverage['middleware/logger.js'][188] = 0; + _$jscoverage['middleware/logger.js'][200] = 0; + _$jscoverage['middleware/logger.js'][201] = 0; + _$jscoverage['middleware/logger.js'][202] = 0; + _$jscoverage['middleware/logger.js'][209] = 0; + _$jscoverage['middleware/logger.js'][215] = 0; + _$jscoverage['middleware/logger.js'][221] = 0; + _$jscoverage['middleware/logger.js'][227] = 0; + _$jscoverage['middleware/logger.js'][228] = 0; + _$jscoverage['middleware/logger.js'][232] = 0; + _$jscoverage['middleware/logger.js'][233] = 0; + _$jscoverage['middleware/logger.js'][234] = 0; + _$jscoverage['middleware/logger.js'][236] = 0; + _$jscoverage['middleware/logger.js'][240] = 0; + _$jscoverage['middleware/logger.js'][253] = 0; + _$jscoverage['middleware/logger.js'][254] = 0; + _$jscoverage['middleware/logger.js'][261] = 0; + _$jscoverage['middleware/logger.js'][262] = 0; + _$jscoverage['middleware/logger.js'][269] = 0; + _$jscoverage['middleware/logger.js'][270] = 0; + _$jscoverage['middleware/logger.js'][277] = 0; + _$jscoverage['middleware/logger.js'][278] = 0; + _$jscoverage['middleware/logger.js'][285] = 0; + _$jscoverage['middleware/logger.js'][286] = 0; + _$jscoverage['middleware/logger.js'][293] = 0; + _$jscoverage['middleware/logger.js'][294] = 0; + _$jscoverage['middleware/logger.js'][301] = 0; + _$jscoverage['middleware/logger.js'][302] = 0; + _$jscoverage['middleware/logger.js'][303] = 0; + _$jscoverage['middleware/logger.js'][304] = 0; + _$jscoverage['middleware/logger.js'][305] = 0; + _$jscoverage['middleware/logger.js'][312] = 0; + _$jscoverage['middleware/logger.js'][313] = 0; + _$jscoverage['middleware/logger.js'][320] = 0; + _$jscoverage['middleware/logger.js'][321] = 0; + _$jscoverage['middleware/logger.js'][328] = 0; + _$jscoverage['middleware/logger.js'][329] = 0; + _$jscoverage['middleware/logger.js'][336] = 0; + _$jscoverage['middleware/logger.js'][337] = 0; +} +_$jscoverage['middleware/logger.js'][12]++; +var bytes = require("bytes"); +_$jscoverage['middleware/logger.js'][18]++; +var buf = []; +_$jscoverage['middleware/logger.js'][24]++; +var defaultBufferDuration = 1000; +_$jscoverage['middleware/logger.js'][90]++; +exports = module.exports = (function logger(options) { + _$jscoverage['middleware/logger.js'][91]++; + if ("object" == typeof options) { + _$jscoverage['middleware/logger.js'][92]++; + options = options || {}; + } + else { + _$jscoverage['middleware/logger.js'][93]++; + if (options) { + _$jscoverage['middleware/logger.js'][94]++; + options = {format: options}; + } + else { + _$jscoverage['middleware/logger.js'][96]++; + options = {}; + } + } + _$jscoverage['middleware/logger.js'][100]++; + var immediate = options.immediate; + _$jscoverage['middleware/logger.js'][103]++; + var fmt = exports[options.format] || options.format || exports["default"]; + _$jscoverage['middleware/logger.js'][106]++; + if ("function" != typeof fmt) { + _$jscoverage['middleware/logger.js'][106]++; + fmt = compile(fmt); + } + _$jscoverage['middleware/logger.js'][109]++; + var stream = options.stream || process.stdout, buffer = options.buffer; + _$jscoverage['middleware/logger.js'][113]++; + if (buffer) { + _$jscoverage['middleware/logger.js'][114]++; + var realStream = stream, interval = "number" == typeof buffer? buffer: defaultBufferDuration; + _$jscoverage['middleware/logger.js'][120]++; + setInterval((function () { + _$jscoverage['middleware/logger.js'][121]++; + if (buf.length) { + _$jscoverage['middleware/logger.js'][122]++; + realStream.write(buf.join("")); + _$jscoverage['middleware/logger.js'][123]++; + buf.length = 0; + } +}), interval); + _$jscoverage['middleware/logger.js'][128]++; + stream = {write: (function (str) { + _$jscoverage['middleware/logger.js'][130]++; + buf.push(str); +})}; + } + _$jscoverage['middleware/logger.js'][135]++; + return (function logger(req, res, next) { + _$jscoverage['middleware/logger.js'][136]++; + req._startTime = new Date(); + _$jscoverage['middleware/logger.js'][139]++; + if (immediate) { + _$jscoverage['middleware/logger.js'][140]++; + var line = fmt(exports, req, res); + _$jscoverage['middleware/logger.js'][141]++; + if (null == line) { + _$jscoverage['middleware/logger.js'][141]++; + return; + } + _$jscoverage['middleware/logger.js'][142]++; + stream.write(line + "\n"); + } + else { + _$jscoverage['middleware/logger.js'][145]++; + var end = res.end; + _$jscoverage['middleware/logger.js'][146]++; + res.end = (function (chunk, encoding) { + _$jscoverage['middleware/logger.js'][147]++; + res.end = end; + _$jscoverage['middleware/logger.js'][148]++; + res.end(chunk, encoding); + _$jscoverage['middleware/logger.js'][149]++; + var line = fmt(exports, req, res); + _$jscoverage['middleware/logger.js'][150]++; + if (null == line) { + _$jscoverage['middleware/logger.js'][150]++; + return; + } + _$jscoverage['middleware/logger.js'][151]++; + stream.write(line + "\n"); +}); + } + _$jscoverage['middleware/logger.js'][156]++; + next(); +}); +}); +_$jscoverage['middleware/logger.js'][168]++; +function compile(fmt) { + _$jscoverage['middleware/logger.js'][169]++; + fmt = fmt.replace(/"/g, "\\\""); + _$jscoverage['middleware/logger.js'][170]++; + var js = " return \"" + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, (function (_, name, arg) { + _$jscoverage['middleware/logger.js'][171]++; + return "\"\n + (tokens[\"" + name + "\"](req, res, \"" + arg + "\") || \"-\") + \""; +})) + "\";"; + _$jscoverage['middleware/logger.js'][173]++; + return new Function("tokens, req, res", js); +} +_$jscoverage['middleware/logger.js'][174]++; +; +_$jscoverage['middleware/logger.js'][186]++; +exports.token = (function (name, fn) { + _$jscoverage['middleware/logger.js'][187]++; + exports[name] = fn; + _$jscoverage['middleware/logger.js'][188]++; + return this; +}); +_$jscoverage['middleware/logger.js'][200]++; +exports.format = (function (name, str) { + _$jscoverage['middleware/logger.js'][201]++; + exports[name] = str; + _$jscoverage['middleware/logger.js'][202]++; + return this; +}); +_$jscoverage['middleware/logger.js'][209]++; +exports.format("default", ":remote-addr - - [:date] \":method :url HTTP/:http-version\" :status :res[content-length] \":referrer\" \":user-agent\""); +_$jscoverage['middleware/logger.js'][215]++; +exports.format("short", ":remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms"); +_$jscoverage['middleware/logger.js'][221]++; +exports.format("tiny", ":method :url :status :res[content-length] - :response-time ms"); +_$jscoverage['middleware/logger.js'][227]++; +exports.format("dev", (function (tokens, req, res) { + _$jscoverage['middleware/logger.js'][228]++; + var status = res.statusCode, len = parseInt(res.getHeader("Content-Length"), 10), color = 32; + _$jscoverage['middleware/logger.js'][232]++; + if (status >= 500) { + _$jscoverage['middleware/logger.js'][232]++; + color = 31; + } + else { + _$jscoverage['middleware/logger.js'][233]++; + if (status >= 400) { + _$jscoverage['middleware/logger.js'][233]++; + color = 33; + } + else { + _$jscoverage['middleware/logger.js'][234]++; + if (status >= 300) { + _$jscoverage['middleware/logger.js'][234]++; + color = 36; + } + } + } + _$jscoverage['middleware/logger.js'][236]++; + len = isNaN(len)? "": len = " - " + bytes(len); + _$jscoverage['middleware/logger.js'][240]++; + return "\u001b[90m" + req.method + " " + req.originalUrl + " " + "\u001b[" + color + "m" + res.statusCode + " \u001b[90m" + (new Date() - req._startTime) + "ms" + len + "\u001b[0m"; +})); +_$jscoverage['middleware/logger.js'][253]++; +exports.token("url", (function (req) { + _$jscoverage['middleware/logger.js'][254]++; + return req.originalUrl || req.url; +})); +_$jscoverage['middleware/logger.js'][261]++; +exports.token("method", (function (req) { + _$jscoverage['middleware/logger.js'][262]++; + return req.method; +})); +_$jscoverage['middleware/logger.js'][269]++; +exports.token("response-time", (function (req) { + _$jscoverage['middleware/logger.js'][270]++; + return new Date() - req._startTime; +})); +_$jscoverage['middleware/logger.js'][277]++; +exports.token("date", (function () { + _$jscoverage['middleware/logger.js'][278]++; + return new Date().toUTCString(); +})); +_$jscoverage['middleware/logger.js'][285]++; +exports.token("status", (function (req, res) { + _$jscoverage['middleware/logger.js'][286]++; + return res.statusCode; +})); +_$jscoverage['middleware/logger.js'][293]++; +exports.token("referrer", (function (req) { + _$jscoverage['middleware/logger.js'][294]++; + return req.headers.referer || req.headers.referrer; +})); +_$jscoverage['middleware/logger.js'][301]++; +exports.token("remote-addr", (function (req) { + _$jscoverage['middleware/logger.js'][302]++; + if (req.ip) { + _$jscoverage['middleware/logger.js'][302]++; + return req.ip; + } + _$jscoverage['middleware/logger.js'][303]++; + var sock = req.socket; + _$jscoverage['middleware/logger.js'][304]++; + if (sock.socket) { + _$jscoverage['middleware/logger.js'][304]++; + return sock.socket.remoteAddress; + } + _$jscoverage['middleware/logger.js'][305]++; + return sock.remoteAddress; +})); +_$jscoverage['middleware/logger.js'][312]++; +exports.token("http-version", (function (req) { + _$jscoverage['middleware/logger.js'][313]++; + return req.httpVersionMajor + "." + req.httpVersionMinor; +})); +_$jscoverage['middleware/logger.js'][320]++; +exports.token("user-agent", (function (req) { + _$jscoverage['middleware/logger.js'][321]++; + return req.headers["user-agent"]; +})); +_$jscoverage['middleware/logger.js'][328]++; +exports.token("req", (function (req, res, field) { + _$jscoverage['middleware/logger.js'][329]++; + return req.headers[field.toLowerCase()]; +})); +_$jscoverage['middleware/logger.js'][336]++; +exports.token("res", (function (req, res, field) { + _$jscoverage['middleware/logger.js'][337]++; + return (res._headers || {})[field.toLowerCase()]; +})); +_$jscoverage['middleware/logger.js'].source = ["/*!"," * Connect - logger"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var bytes = require('bytes');","","/*!"," * Log buffer."," */","","var buf = [];","","/*!"," * Default log buffer duration."," */","","var defaultBufferDuration = 1000;","","/**"," * Logger:"," *"," * Log requests with the given `options` or a `format` string."," *"," * Options:"," *"," * - `format` Format string, see below for tokens"," * - `stream` Output stream, defaults to _stdout_"," * - `buffer` Buffer duration, defaults to 1000ms when _true_"," * - `immediate` Write log line on request instead of response (for response times)"," *"," * Tokens:"," *"," * - `:req[header]` ex: `:req[Accept]`"," * - `:res[header]` ex: `:res[Content-Length]`"," * - `:http-version`"," * - `:response-time`"," * - `:remote-addr`"," * - `:date`"," * - `:method`"," * - `:url`"," * - `:referrer`"," * - `:user-agent`"," * - `:status`"," *"," * Formats:"," *"," * Pre-defined formats that ship with connect:"," *"," * - `default` ':remote-addr - - [:date] \":method :url HTTP/:http-version\" :status :res[content-length] \":referrer\" \":user-agent\"'"," * - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'"," * - `tiny` ':method :url :status :res[content-length] - :response-time ms'"," * - `dev` concise output colored by response status for development use"," *"," * Examples:"," *"," * connect.logger() // default"," * connect.logger('short')"," * connect.logger('tiny')"," * connect.logger({ immediate: true, format: 'dev' })"," * connect.logger(':method :url - :referrer')"," * connect.logger(':req[content-type] -> :res[content-type]')"," * connect.logger(function(tokens, req, res){ return 'some format string' })"," *"," * Defining Tokens:"," *"," * To define a token, simply invoke `connect.logger.token()` with the"," * name and a callback function. The value returned is then available"," * as \":type\" in this case."," *"," * connect.logger.token('type', function(req, res){ return req.headers['content-type']; })"," *"," * Defining Formats:"," *"," * All default formats are defined this way, however it's public API as well:"," *"," * connect.logger.format('name', 'string or function')"," *"," * @param {String|Function|Object} format or options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function logger(options) {"," if ('object' == typeof options) {"," options = options || {};"," } else if (options) {"," options = { format: options };"," } else {"," options = {};"," }",""," // output on request instead of response"," var immediate = options.immediate;",""," // format name"," var fmt = exports[options.format] || options.format || exports.default;",""," // compile format"," if ('function' != typeof fmt) fmt = compile(fmt);",""," // options"," var stream = options.stream || process.stdout"," , buffer = options.buffer;",""," // buffering support"," if (buffer) {"," var realStream = stream"," , interval = 'number' == typeof buffer"," ? buffer"," : defaultBufferDuration;",""," // flush interval"," setInterval(function(){"," if (buf.length) {"," realStream.write(buf.join(''));"," buf.length = 0;"," }"," }, interval); ",""," // swap the stream"," stream = {"," write: function(str){"," buf.push(str);"," }"," };"," }",""," return function logger(req, res, next) {"," req._startTime = new Date;",""," // immediate"," if (immediate) {"," var line = fmt(exports, req, res);"," if (null == line) return;"," stream.write(line + '\\n');"," // proxy end to output logging"," } else {"," var end = res.end;"," res.end = function(chunk, encoding){"," res.end = end;"," res.end(chunk, encoding);"," var line = fmt(exports, req, res);"," if (null == line) return;"," stream.write(line + '\\n');"," };"," }","",""," next();"," };","};","","/**"," * Compile `fmt` into a function."," *"," * @param {String} fmt"," * @return {Function}"," * @api private"," */","","function compile(fmt) {"," fmt = fmt.replace(/\"/g, '\\\\\"');"," var js = ' return \"' + fmt.replace(/:([-\\w]{2,})(?:\\[([^\\]]+)\\])?/g, function(_, name, arg){"," return '\"\\n + (tokens[\"' + name + '\"](req, res, \"' + arg + '\") || \"-\") + \"';"," }) + '\";'"," return new Function('tokens, req, res', js);","};","","/**"," * Define a token function with the given `name`,"," * and callback `fn(req, res)`."," *"," * @param {String} name"," * @param {Function} fn"," * @return {Object} exports for chaining"," * @api public"," */","","exports.token = function(name, fn) {"," exports[name] = fn;"," return this;","};","","/**"," * Define a `fmt` with the given `name`."," *"," * @param {String} name"," * @param {String|Function} fmt"," * @return {Object} exports for chaining"," * @api public"," */","","exports.format = function(name, str){"," exports[name] = str;"," return this;","};","","/**"," * Default format."," */","","exports.format('default', ':remote-addr - - [:date] \":method :url HTTP/:http-version\" :status :res[content-length] \":referrer\" \":user-agent\"');","","/**"," * Short format."," */","","exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms');","","/**"," * Tiny format."," */","","exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms');","","/**"," * dev (colored)"," */","","exports.format('dev', function(tokens, req, res){"," var status = res.statusCode"," , len = parseInt(res.getHeader('Content-Length'), 10)"," , color = 32;",""," if (status >= 500) color = 31"," else if (status >= 400) color = 33"," else if (status >= 300) color = 36;",""," len = isNaN(len)"," ? ''"," : len = ' - ' + bytes(len);",""," return '\\033[90m' + req.method"," + ' ' + req.originalUrl + ' '"," + '\\033[' + color + 'm' + res.statusCode"," + ' \\033[90m'"," + (new Date - req._startTime)"," + 'ms' + len"," + '\\033[0m';","});","","/**"," * request url"," */","","exports.token('url', function(req){"," return req.originalUrl || req.url;","});","","/**"," * request method"," */","","exports.token('method', function(req){"," return req.method;","});","","/**"," * response time in milliseconds"," */","","exports.token('response-time', function(req){"," return new Date - req._startTime;","});","","/**"," * UTC date"," */","","exports.token('date', function(){"," return new Date().toUTCString();","});","","/**"," * response status code"," */","","exports.token('status', function(req, res){"," return res.statusCode;","});","","/**"," * normalized referrer"," */","","exports.token('referrer', function(req){"," return req.headers['referer'] || req.headers['referrer'];","});","","/**"," * remote address"," */","","exports.token('remote-addr', function(req){"," if (req.ip) return req.ip;"," var sock = req.socket;"," if (sock.socket) return sock.socket.remoteAddress;"," return sock.remoteAddress;","});","","/**"," * HTTP version"," */","","exports.token('http-version', function(req){"," return req.httpVersionMajor + '.' + req.httpVersionMinor;","});","","/**"," * UA string"," */","","exports.token('user-agent', function(req){"," return req.headers['user-agent'];","});","","/**"," * request header"," */","","exports.token('req', function(req, res, field){"," return req.headers[field.toLowerCase()];","});","","/**"," * response header"," */","","exports.token('res', function(req, res, field){"," return (res._headers || {})[field.toLowerCase()];","});",""]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/methodOverride.js b/node_modules/express/node_modules/connect/lib-cov/middleware/methodOverride.js new file mode 100644 index 0000000..0a9118c --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/methodOverride.js @@ -0,0 +1,42 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/methodOverride.js']) { + _$jscoverage['middleware/methodOverride.js'] = []; + _$jscoverage['middleware/methodOverride.js'][23] = 0; + _$jscoverage['middleware/methodOverride.js'][24] = 0; + _$jscoverage['middleware/methodOverride.js'][25] = 0; + _$jscoverage['middleware/methodOverride.js'][26] = 0; + _$jscoverage['middleware/methodOverride.js'][29] = 0; + _$jscoverage['middleware/methodOverride.js'][30] = 0; + _$jscoverage['middleware/methodOverride.js'][31] = 0; + _$jscoverage['middleware/methodOverride.js'][33] = 0; + _$jscoverage['middleware/methodOverride.js'][34] = 0; + _$jscoverage['middleware/methodOverride.js'][37] = 0; +} +_$jscoverage['middleware/methodOverride.js'][23]++; +module.exports = (function methodOverride(key) { + _$jscoverage['middleware/methodOverride.js'][24]++; + key = key || "_method"; + _$jscoverage['middleware/methodOverride.js'][25]++; + return (function methodOverride(req, res, next) { + _$jscoverage['middleware/methodOverride.js'][26]++; + req.originalMethod = req.originalMethod || req.method; + _$jscoverage['middleware/methodOverride.js'][29]++; + if (req.body && key in req.body) { + _$jscoverage['middleware/methodOverride.js'][30]++; + req.method = req.body[key].toUpperCase(); + _$jscoverage['middleware/methodOverride.js'][31]++; + delete req.body[key]; + } + else { + _$jscoverage['middleware/methodOverride.js'][33]++; + if (req.headers["x-http-method-override"]) { + _$jscoverage['middleware/methodOverride.js'][34]++; + req.method = req.headers["x-http-method-override"].toUpperCase(); + } + } + _$jscoverage['middleware/methodOverride.js'][37]++; + next(); +}); +}); +_$jscoverage['middleware/methodOverride.js'].source = ["","/*!"," * Connect - methodOverride"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Method Override:"," * "," * Provides faux HTTP method support."," * "," * Pass an optional `key` to use when checking for"," * a method override, othewise defaults to _\\_method_."," * The original method is available via `req.originalMethod`."," *"," * @param {String} key"," * @return {Function}"," * @api public"," */","","module.exports = function methodOverride(key){"," key = key || \"_method\";"," return function methodOverride(req, res, next) {"," req.originalMethod = req.originalMethod || req.method;",""," // req.body"," if (req.body && key in req.body) {"," req.method = req.body[key].toUpperCase();"," delete req.body[key];"," // check X-HTTP-Method-Override"," } else if (req.headers['x-http-method-override']) {"," req.method = req.headers['x-http-method-override'].toUpperCase();"," }"," "," next();"," };","};",""]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/multipart.js b/node_modules/express/node_modules/connect/lib-cov/middleware/multipart.js new file mode 100644 index 0000000..dfcde09 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/multipart.js @@ -0,0 +1,183 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/multipart.js']) { + _$jscoverage['middleware/multipart.js'] = []; + _$jscoverage['middleware/multipart.js'][12] = 0; + _$jscoverage['middleware/multipart.js'][21] = 0; + _$jscoverage['middleware/multipart.js'][22] = 0; + _$jscoverage['middleware/multipart.js'][52] = 0; + _$jscoverage['middleware/multipart.js'][53] = 0; + _$jscoverage['middleware/multipart.js'][55] = 0; + _$jscoverage['middleware/multipart.js'][59] = 0; + _$jscoverage['middleware/multipart.js'][60] = 0; + _$jscoverage['middleware/multipart.js'][61] = 0; + _$jscoverage['middleware/multipart.js'][62] = 0; + _$jscoverage['middleware/multipart.js'][64] = 0; + _$jscoverage['middleware/multipart.js'][67] = 0; + _$jscoverage['middleware/multipart.js'][70] = 0; + _$jscoverage['middleware/multipart.js'][73] = 0; + _$jscoverage['middleware/multipart.js'][76] = 0; + _$jscoverage['middleware/multipart.js'][77] = 0; + _$jscoverage['middleware/multipart.js'][79] = 0; + _$jscoverage['middleware/multipart.js'][84] = 0; + _$jscoverage['middleware/multipart.js'][85] = 0; + _$jscoverage['middleware/multipart.js'][88] = 0; + _$jscoverage['middleware/multipart.js'][89] = 0; + _$jscoverage['middleware/multipart.js'][90] = 0; + _$jscoverage['middleware/multipart.js'][91] = 0; + _$jscoverage['middleware/multipart.js'][92] = 0; + _$jscoverage['middleware/multipart.js'][94] = 0; + _$jscoverage['middleware/multipart.js'][98] = 0; + _$jscoverage['middleware/multipart.js'][99] = 0; + _$jscoverage['middleware/multipart.js'][102] = 0; + _$jscoverage['middleware/multipart.js'][103] = 0; + _$jscoverage['middleware/multipart.js'][106] = 0; + _$jscoverage['middleware/multipart.js'][107] = 0; + _$jscoverage['middleware/multipart.js'][108] = 0; + _$jscoverage['middleware/multipart.js'][109] = 0; + _$jscoverage['middleware/multipart.js'][111] = 0; + _$jscoverage['middleware/multipart.js'][114] = 0; + _$jscoverage['middleware/multipart.js'][115] = 0; + _$jscoverage['middleware/multipart.js'][116] = 0; + _$jscoverage['middleware/multipart.js'][117] = 0; + _$jscoverage['middleware/multipart.js'][118] = 0; + _$jscoverage['middleware/multipart.js'][119] = 0; + _$jscoverage['middleware/multipart.js'][121] = 0; + _$jscoverage['middleware/multipart.js'][125] = 0; + _$jscoverage['middleware/multipart.js'][127] = 0; + _$jscoverage['middleware/multipart.js'][128] = 0; + _$jscoverage['middleware/multipart.js'][129] = 0; +} +_$jscoverage['middleware/multipart.js'][12]++; +var formidable = require("formidable"), _limit = require("./limit"), utils = require("../utils"), qs = require("qs"); +_$jscoverage['middleware/multipart.js'][21]++; +function noop(req, res, next) { + _$jscoverage['middleware/multipart.js'][22]++; + next(); +} +_$jscoverage['middleware/multipart.js'][52]++; +exports = module.exports = (function (options) { + _$jscoverage['middleware/multipart.js'][53]++; + options = options || {}; + _$jscoverage['middleware/multipart.js'][55]++; + var limit = options.limit? _limit(options.limit): noop; + _$jscoverage['middleware/multipart.js'][59]++; + return (function multipart(req, res, next) { + _$jscoverage['middleware/multipart.js'][60]++; + if (req._body) { + _$jscoverage['middleware/multipart.js'][60]++; + return next(); + } + _$jscoverage['middleware/multipart.js'][61]++; + req.body = req.body || {}; + _$jscoverage['middleware/multipart.js'][62]++; + req.files = req.files || {}; + _$jscoverage['middleware/multipart.js'][64]++; + if (! utils.hasBody(req)) { + _$jscoverage['middleware/multipart.js'][64]++; + return next(); + } + _$jscoverage['middleware/multipart.js'][67]++; + if ("GET" == req.method || "HEAD" == req.method) { + _$jscoverage['middleware/multipart.js'][67]++; + return next(); + } + _$jscoverage['middleware/multipart.js'][70]++; + if ("multipart/form-data" != utils.mime(req)) { + _$jscoverage['middleware/multipart.js'][70]++; + return next(); + } + _$jscoverage['middleware/multipart.js'][73]++; + req._body = true; + _$jscoverage['middleware/multipart.js'][76]++; + limit(req, res, (function (err) { + _$jscoverage['middleware/multipart.js'][77]++; + if (err) { + _$jscoverage['middleware/multipart.js'][77]++; + return next(err); + } + _$jscoverage['middleware/multipart.js'][79]++; + var form = new formidable.IncomingForm(), data = {}, files = {}, done; + _$jscoverage['middleware/multipart.js'][84]++; + Object.keys(options).forEach((function (key) { + _$jscoverage['middleware/multipart.js'][85]++; + form[key] = options[key]; +})); + _$jscoverage['middleware/multipart.js'][88]++; + function ondata(name, val, data) { + _$jscoverage['middleware/multipart.js'][89]++; + if (Array.isArray(data[name])) { + _$jscoverage['middleware/multipart.js'][90]++; + data[name].push(val); + } + else { + _$jscoverage['middleware/multipart.js'][91]++; + if (data[name]) { + _$jscoverage['middleware/multipart.js'][92]++; + data[name] = [data[name], val]; + } + else { + _$jscoverage['middleware/multipart.js'][94]++; + data[name] = val; + } + } +} + _$jscoverage['middleware/multipart.js'][98]++; + form.on("field", (function (name, val) { + _$jscoverage['middleware/multipart.js'][99]++; + ondata(name, val, data); +})); + _$jscoverage['middleware/multipart.js'][102]++; + form.on("file", (function (name, val) { + _$jscoverage['middleware/multipart.js'][103]++; + ondata(name, val, files); +})); + _$jscoverage['middleware/multipart.js'][106]++; + form.on("error", (function (err) { + _$jscoverage['middleware/multipart.js'][107]++; + if (! options.defer) { + _$jscoverage['middleware/multipart.js'][108]++; + err.status = 400; + _$jscoverage['middleware/multipart.js'][109]++; + next(err); + } + _$jscoverage['middleware/multipart.js'][111]++; + done = true; +})); + _$jscoverage['middleware/multipart.js'][114]++; + form.on("end", (function () { + _$jscoverage['middleware/multipart.js'][115]++; + if (done) { + _$jscoverage['middleware/multipart.js'][115]++; + return; + } + _$jscoverage['middleware/multipart.js'][116]++; + try { + _$jscoverage['middleware/multipart.js'][117]++; + req.body = qs.parse(data); + _$jscoverage['middleware/multipart.js'][118]++; + req.files = qs.parse(files); + _$jscoverage['middleware/multipart.js'][119]++; + if (! options.defer) { + _$jscoverage['middleware/multipart.js'][119]++; + next(); + } + } + catch (err) { + _$jscoverage['middleware/multipart.js'][121]++; + form.emit("error", err); + } +})); + _$jscoverage['middleware/multipart.js'][125]++; + form.parse(req); + _$jscoverage['middleware/multipart.js'][127]++; + if (options.defer) { + _$jscoverage['middleware/multipart.js'][128]++; + req.form = form; + _$jscoverage['middleware/multipart.js'][129]++; + next(); + } +})); +}); +}); +_$jscoverage['middleware/multipart.js'].source = ["/*!"," * Connect - multipart"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var formidable = require('formidable')"," , _limit = require('./limit')"," , utils = require('../utils')"," , qs = require('qs');","","/**"," * noop middleware."," */","","function noop(req, res, next) {"," next();","}","","/**"," * Multipart:"," * "," * Parse multipart/form-data request bodies,"," * providing the parsed object as `req.body`"," * and `req.files`."," *"," * Configuration:"," *"," * The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s"," * `IncomingForm` object, allowing you to configure the upload directory,"," * size limits, etc. For example if you wish to change the upload dir do the following."," *"," * app.use(connect.multipart({ uploadDir: path }));"," *"," * Options:"," *"," * - `limit` byte limit defaulting to none"," * - `defer` defers processing and exposes the Formidable form object as `req.form`."," * `next()` is called without waiting for the form's \"end\" event."," * This option is useful if you need to bind to the \"progress\" event, for example."," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function(options){"," options = options || {};",""," var limit = options.limit"," ? _limit(options.limit)"," : noop;",""," return function multipart(req, res, next) {"," if (req._body) return next();"," req.body = req.body || {};"," req.files = req.files || {};",""," if (!utils.hasBody(req)) return next();",""," // ignore GET"," if ('GET' == req.method || 'HEAD' == req.method) return next();",""," // check Content-Type"," if ('multipart/form-data' != utils.mime(req)) return next();",""," // flag as parsed"," req._body = true;",""," // parse"," limit(req, res, function(err){"," if (err) return next(err);",""," var form = new formidable.IncomingForm"," , data = {}"," , files = {}"," , done;",""," Object.keys(options).forEach(function(key){"," form[key] = options[key];"," });",""," function ondata(name, val, data){"," if (Array.isArray(data[name])) {"," data[name].push(val);"," } else if (data[name]) {"," data[name] = [data[name], val];"," } else {"," data[name] = val;"," }"," }",""," form.on('field', function(name, val){"," ondata(name, val, data);"," });",""," form.on('file', function(name, val){"," ondata(name, val, files);"," });",""," form.on('error', function(err){"," if (!options.defer) {"," err.status = 400;"," next(err);"," }"," done = true;"," });",""," form.on('end', function(){"," if (done) return;"," try {"," req.body = qs.parse(data);"," req.files = qs.parse(files);"," if (!options.defer) next();"," } catch (err) {"," form.emit('error', err);"," }"," });",""," form.parse(req);",""," if (options.defer) {"," req.form = form;"," next();"," }"," });"," }","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/query.js b/node_modules/express/node_modules/connect/lib-cov/middleware/query.js new file mode 100644 index 0000000..bd27ff6 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/query.js @@ -0,0 +1,27 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/query.js']) { + _$jscoverage['middleware/query.js'] = []; + _$jscoverage['middleware/query.js'][12] = 0; + _$jscoverage['middleware/query.js'][36] = 0; + _$jscoverage['middleware/query.js'][37] = 0; + _$jscoverage['middleware/query.js'][38] = 0; + _$jscoverage['middleware/query.js'][39] = 0; + _$jscoverage['middleware/query.js'][44] = 0; +} +_$jscoverage['middleware/query.js'][12]++; +var qs = require("qs"), parse = require("../utils").parseUrl; +_$jscoverage['middleware/query.js'][36]++; +module.exports = (function query(options) { + _$jscoverage['middleware/query.js'][37]++; + return (function query(req, res, next) { + _$jscoverage['middleware/query.js'][38]++; + if (! req.query) { + _$jscoverage['middleware/query.js'][39]++; + req.query = ~ req.url.indexOf("?")? qs.parse(parse(req).query, options): {}; + } + _$jscoverage['middleware/query.js'][44]++; + next(); +}); +}); +_$jscoverage['middleware/query.js'].source = ["/*!"," * Connect - query"," * Copyright(c) 2011 TJ Holowaychuk"," * Copyright(c) 2011 Sencha Inc."," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var qs = require('qs')"," , parse = require('../utils').parseUrl;","","/**"," * Query:"," *"," * Automatically parse the query-string when available,"," * populating the `req.query` object."," *"," * Examples:"," *"," * connect()"," * .use(connect.query())"," * .use(function(req, res){"," * res.end(JSON.stringify(req.query));"," * });"," *"," * The `options` passed are provided to qs.parse function."," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","module.exports = function query(options){"," return function query(req, res, next){"," if (!req.query) {"," req.query = ~req.url.indexOf('?')"," ? qs.parse(parse(req).query, options)"," : {};"," }",""," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/responseTime.js b/node_modules/express/node_modules/connect/lib-cov/middleware/responseTime.js new file mode 100644 index 0000000..954e040 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/responseTime.js @@ -0,0 +1,39 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/responseTime.js']) { + _$jscoverage['middleware/responseTime.js'] = []; + _$jscoverage['middleware/responseTime.js'][18] = 0; + _$jscoverage['middleware/responseTime.js'][19] = 0; + _$jscoverage['middleware/responseTime.js'][20] = 0; + _$jscoverage['middleware/responseTime.js'][22] = 0; + _$jscoverage['middleware/responseTime.js'][23] = 0; + _$jscoverage['middleware/responseTime.js'][25] = 0; + _$jscoverage['middleware/responseTime.js'][26] = 0; + _$jscoverage['middleware/responseTime.js'][27] = 0; + _$jscoverage['middleware/responseTime.js'][30] = 0; +} +_$jscoverage['middleware/responseTime.js'][18]++; +module.exports = (function responseTime() { + _$jscoverage['middleware/responseTime.js'][19]++; + return (function (req, res, next) { + _$jscoverage['middleware/responseTime.js'][20]++; + var start = new Date(); + _$jscoverage['middleware/responseTime.js'][22]++; + if (res._responseTime) { + _$jscoverage['middleware/responseTime.js'][22]++; + return next(); + } + _$jscoverage['middleware/responseTime.js'][23]++; + res._responseTime = true; + _$jscoverage['middleware/responseTime.js'][25]++; + res.on("header", (function () { + _$jscoverage['middleware/responseTime.js'][26]++; + var duration = new Date() - start; + _$jscoverage['middleware/responseTime.js'][27]++; + res.setHeader("X-Response-Time", duration + "ms"); +})); + _$jscoverage['middleware/responseTime.js'][30]++; + next(); +}); +}); +_$jscoverage['middleware/responseTime.js'].source = ["","/*!"," * Connect - responseTime"," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Reponse time:"," *"," * Adds the `X-Response-Time` header displaying the response"," * duration in milliseconds."," *"," * @return {Function}"," * @api public"," */","","module.exports = function responseTime(){"," return function(req, res, next){"," var start = new Date;",""," if (res._responseTime) return next();"," res._responseTime = true;",""," res.on('header', function(){"," var duration = new Date - start;"," res.setHeader('X-Response-Time', duration + 'ms');"," });",""," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/session.js b/node_modules/express/node_modules/connect/lib-cov/middleware/session.js new file mode 100644 index 0000000..5ff99f8 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/session.js @@ -0,0 +1,321 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/session.js']) { + _$jscoverage['middleware/session.js'] = []; + _$jscoverage['middleware/session.js'][13] = 0; + _$jscoverage['middleware/session.js'][25] = 0; + _$jscoverage['middleware/session.js'][31] = 0; + _$jscoverage['middleware/session.js'][37] = 0; + _$jscoverage['middleware/session.js'][38] = 0; + _$jscoverage['middleware/session.js'][39] = 0; + _$jscoverage['middleware/session.js'][40] = 0; + _$jscoverage['middleware/session.js'][46] = 0; + _$jscoverage['middleware/session.js'][188] = 0; + _$jscoverage['middleware/session.js'][189] = 0; + _$jscoverage['middleware/session.js'][198] = 0; + _$jscoverage['middleware/session.js'][199] = 0; + _$jscoverage['middleware/session.js'][203] = 0; + _$jscoverage['middleware/session.js'][204] = 0; + _$jscoverage['middleware/session.js'][205] = 0; + _$jscoverage['middleware/session.js'][206] = 0; + _$jscoverage['middleware/session.js'][209] = 0; + _$jscoverage['middleware/session.js'][210] = 0; + _$jscoverage['middleware/session.js'][212] = 0; + _$jscoverage['middleware/session.js'][214] = 0; + _$jscoverage['middleware/session.js'][218] = 0; + _$jscoverage['middleware/session.js'][221] = 0; + _$jscoverage['middleware/session.js'][225] = 0; + _$jscoverage['middleware/session.js'][228] = 0; + _$jscoverage['middleware/session.js'][231] = 0; + _$jscoverage['middleware/session.js'][235] = 0; + _$jscoverage['middleware/session.js'][238] = 0; + _$jscoverage['middleware/session.js'][241] = 0; + _$jscoverage['middleware/session.js'][243] = 0; + _$jscoverage['middleware/session.js'][244] = 0; + _$jscoverage['middleware/session.js'][248] = 0; + _$jscoverage['middleware/session.js'][249] = 0; + _$jscoverage['middleware/session.js'][250] = 0; + _$jscoverage['middleware/session.js'][257] = 0; + _$jscoverage['middleware/session.js'][260] = 0; + _$jscoverage['middleware/session.js'][261] = 0; + _$jscoverage['middleware/session.js'][263] = 0; + _$jscoverage['middleware/session.js'][264] = 0; + _$jscoverage['middleware/session.js'][267] = 0; + _$jscoverage['middleware/session.js'][268] = 0; + _$jscoverage['middleware/session.js'][269] = 0; + _$jscoverage['middleware/session.js'][270] = 0; + _$jscoverage['middleware/session.js'][274] = 0; + _$jscoverage['middleware/session.js'][275] = 0; + _$jscoverage['middleware/session.js'][276] = 0; + _$jscoverage['middleware/session.js'][277] = 0; + _$jscoverage['middleware/session.js'][278] = 0; + _$jscoverage['middleware/session.js'][279] = 0; + _$jscoverage['middleware/session.js'][280] = 0; + _$jscoverage['middleware/session.js'][281] = 0; + _$jscoverage['middleware/session.js'][282] = 0; + _$jscoverage['middleware/session.js'][287] = 0; + _$jscoverage['middleware/session.js'][288] = 0; + _$jscoverage['middleware/session.js'][292] = 0; + _$jscoverage['middleware/session.js'][295] = 0; + _$jscoverage['middleware/session.js'][296] = 0; + _$jscoverage['middleware/session.js'][297] = 0; + _$jscoverage['middleware/session.js'][298] = 0; + _$jscoverage['middleware/session.js'][299] = 0; + _$jscoverage['middleware/session.js'][303] = 0; + _$jscoverage['middleware/session.js'][304] = 0; + _$jscoverage['middleware/session.js'][305] = 0; + _$jscoverage['middleware/session.js'][307] = 0; + _$jscoverage['middleware/session.js'][308] = 0; + _$jscoverage['middleware/session.js'][309] = 0; + _$jscoverage['middleware/session.js'][310] = 0; + _$jscoverage['middleware/session.js'][314] = 0; + _$jscoverage['middleware/session.js'][315] = 0; + _$jscoverage['middleware/session.js'][316] = 0; + _$jscoverage['middleware/session.js'][317] = 0; + _$jscoverage['middleware/session.js'][318] = 0; + _$jscoverage['middleware/session.js'][320] = 0; + _$jscoverage['middleware/session.js'][323] = 0; + _$jscoverage['middleware/session.js'][324] = 0; + _$jscoverage['middleware/session.js'][325] = 0; + _$jscoverage['middleware/session.js'][326] = 0; + _$jscoverage['middleware/session.js'][329] = 0; + _$jscoverage['middleware/session.js'][330] = 0; + _$jscoverage['middleware/session.js'][331] = 0; + _$jscoverage['middleware/session.js'][332] = 0; + _$jscoverage['middleware/session.js'][333] = 0; + _$jscoverage['middleware/session.js'][337] = 0; + _$jscoverage['middleware/session.js'][348] = 0; + _$jscoverage['middleware/session.js'][349] = 0; + _$jscoverage['middleware/session.js'][350] = 0; +} +_$jscoverage['middleware/session.js'][13]++; +var Session = require("./session/session"), debug = require("debug")("connect:session"), MemoryStore = require("./session/memory"), signature = require("cookie-signature"), Cookie = require("./session/cookie"), Store = require("./session/store"), utils = require("./../utils"), parse = utils.parseUrl, crc16 = require("crc").crc16; +_$jscoverage['middleware/session.js'][25]++; +var env = process.env.NODE_ENV; +_$jscoverage['middleware/session.js'][31]++; +exports = module.exports = session; +_$jscoverage['middleware/session.js'][37]++; +exports.Store = Store; +_$jscoverage['middleware/session.js'][38]++; +exports.Cookie = Cookie; +_$jscoverage['middleware/session.js'][39]++; +exports.Session = Session; +_$jscoverage['middleware/session.js'][40]++; +exports.MemoryStore = MemoryStore; +_$jscoverage['middleware/session.js'][46]++; +var warning = "Warning: connection.session() MemoryStore is not\ndesigned for a production environment, as it will leak\nmemory, and will not scale past a single process."; +_$jscoverage['middleware/session.js'][188]++; +function session(options) { + _$jscoverage['middleware/session.js'][189]++; + var options = options || {}, key = options.key || "connect.sid", store = options.store || new MemoryStore(), cookie = options.cookie || {}, trustProxy = options.proxy, storeReady = true; + _$jscoverage['middleware/session.js'][198]++; + if ("production" == env && store instanceof MemoryStore) { + _$jscoverage['middleware/session.js'][199]++; + console.warn(warning); + } + _$jscoverage['middleware/session.js'][203]++; + store.generate = (function (req) { + _$jscoverage['middleware/session.js'][204]++; + req.sessionID = utils.uid(24); + _$jscoverage['middleware/session.js'][205]++; + req.session = new Session(req); + _$jscoverage['middleware/session.js'][206]++; + req.session.cookie = new Cookie(cookie); +}); + _$jscoverage['middleware/session.js'][209]++; + store.on("disconnect", (function () { + _$jscoverage['middleware/session.js'][209]++; + storeReady = false; +})); + _$jscoverage['middleware/session.js'][210]++; + store.on("connect", (function () { + _$jscoverage['middleware/session.js'][210]++; + storeReady = true; +})); + _$jscoverage['middleware/session.js'][212]++; + return (function session(req, res, next) { + _$jscoverage['middleware/session.js'][214]++; + if (req.session) { + _$jscoverage['middleware/session.js'][214]++; + return next(); + } + _$jscoverage['middleware/session.js'][218]++; + if (! storeReady) { + _$jscoverage['middleware/session.js'][218]++; + return debug("store is disconnected"), next(); + } + _$jscoverage['middleware/session.js'][221]++; + if (0 != req.originalUrl.indexOf(cookie.path || "/")) { + _$jscoverage['middleware/session.js'][221]++; + return next(); + } + _$jscoverage['middleware/session.js'][225]++; + var secret = options.secret || req.secret; + _$jscoverage['middleware/session.js'][228]++; + if (! secret) { + _$jscoverage['middleware/session.js'][228]++; + throw new Error("`secret` option required for sessions"); + } + _$jscoverage['middleware/session.js'][231]++; + var originalHash, originalId; + _$jscoverage['middleware/session.js'][235]++; + req.sessionStore = store; + _$jscoverage['middleware/session.js'][238]++; + var rawCookie = req.cookies[key]; + _$jscoverage['middleware/session.js'][241]++; + var unsignedCookie = req.signedCookies[key]; + _$jscoverage['middleware/session.js'][243]++; + if (! unsignedCookie && rawCookie) { + _$jscoverage['middleware/session.js'][244]++; + unsignedCookie = utils.parseSignedCookie(rawCookie, secret); + } + _$jscoverage['middleware/session.js'][248]++; + res.on("header", (function () { + _$jscoverage['middleware/session.js'][249]++; + if (! req.session) { + _$jscoverage['middleware/session.js'][249]++; + return; + } + _$jscoverage['middleware/session.js'][250]++; + var cookie = req.session.cookie, proto = (req.headers["x-forwarded-proto"] || "").toLowerCase(), tls = req.connection.encrypted || (trustProxy && "https" == proto), secured = cookie.secure && tls, isNew = unsignedCookie != req.sessionID; + _$jscoverage['middleware/session.js'][257]++; + if (cookie.secure && ! secured) { + _$jscoverage['middleware/session.js'][257]++; + return debug("not secured"); + } + _$jscoverage['middleware/session.js'][260]++; + if (null == cookie.expires) { + _$jscoverage['middleware/session.js'][261]++; + if (! isNew) { + _$jscoverage['middleware/session.js'][261]++; + return debug("already set browser-session cookie"); + } + } + else { + _$jscoverage['middleware/session.js'][263]++; + if (originalHash == hash(req.session) && originalId == req.session.id) { + _$jscoverage['middleware/session.js'][264]++; + return debug("unmodified session"); + } + } + _$jscoverage['middleware/session.js'][267]++; + var val = "s:" + signature.sign(req.sessionID, secret); + _$jscoverage['middleware/session.js'][268]++; + val = cookie.serialize(key, val); + _$jscoverage['middleware/session.js'][269]++; + debug("set-cookie %s", val); + _$jscoverage['middleware/session.js'][270]++; + res.setHeader("Set-Cookie", val); +})); + _$jscoverage['middleware/session.js'][274]++; + var end = res.end; + _$jscoverage['middleware/session.js'][275]++; + res.end = (function (data, encoding) { + _$jscoverage['middleware/session.js'][276]++; + res.end = end; + _$jscoverage['middleware/session.js'][277]++; + if (! req.session) { + _$jscoverage['middleware/session.js'][277]++; + return res.end(data, encoding); + } + _$jscoverage['middleware/session.js'][278]++; + debug("saving"); + _$jscoverage['middleware/session.js'][279]++; + req.session.resetMaxAge(); + _$jscoverage['middleware/session.js'][280]++; + req.session.save((function () { + _$jscoverage['middleware/session.js'][281]++; + debug("saved"); + _$jscoverage['middleware/session.js'][282]++; + res.end(data, encoding); +})); +}); + _$jscoverage['middleware/session.js'][287]++; + function generate() { + _$jscoverage['middleware/session.js'][288]++; + store.generate(req); +} + _$jscoverage['middleware/session.js'][292]++; + req.sessionID = unsignedCookie; + _$jscoverage['middleware/session.js'][295]++; + if (! req.sessionID) { + _$jscoverage['middleware/session.js'][296]++; + debug("no SID sent, generating session"); + _$jscoverage['middleware/session.js'][297]++; + generate(); + _$jscoverage['middleware/session.js'][298]++; + next(); + _$jscoverage['middleware/session.js'][299]++; + return; + } + _$jscoverage['middleware/session.js'][303]++; + var pause = utils.pause(req); + _$jscoverage['middleware/session.js'][304]++; + debug("fetching %s", req.sessionID); + _$jscoverage['middleware/session.js'][305]++; + store.get(req.sessionID, (function (err, sess) { + _$jscoverage['middleware/session.js'][307]++; + var _next = next; + _$jscoverage['middleware/session.js'][308]++; + next = (function (err) { + _$jscoverage['middleware/session.js'][309]++; + _next(err); + _$jscoverage['middleware/session.js'][310]++; + pause.resume(); +}); + _$jscoverage['middleware/session.js'][314]++; + if (err) { + _$jscoverage['middleware/session.js'][315]++; + debug("error"); + _$jscoverage['middleware/session.js'][316]++; + if ("ENOENT" == err.code) { + _$jscoverage['middleware/session.js'][317]++; + generate(); + _$jscoverage['middleware/session.js'][318]++; + next(); + } + else { + _$jscoverage['middleware/session.js'][320]++; + next(err); + } + } + else { + _$jscoverage['middleware/session.js'][323]++; + if (! sess) { + _$jscoverage['middleware/session.js'][324]++; + debug("no session found"); + _$jscoverage['middleware/session.js'][325]++; + generate(); + _$jscoverage['middleware/session.js'][326]++; + next(); + } + else { + _$jscoverage['middleware/session.js'][329]++; + debug("session found"); + _$jscoverage['middleware/session.js'][330]++; + store.createSession(req, sess); + _$jscoverage['middleware/session.js'][331]++; + originalId = req.sessionID; + _$jscoverage['middleware/session.js'][332]++; + originalHash = hash(sess); + _$jscoverage['middleware/session.js'][333]++; + next(); + } + } +})); +}); +} +_$jscoverage['middleware/session.js'][337]++; +; +_$jscoverage['middleware/session.js'][348]++; +function hash(sess) { + _$jscoverage['middleware/session.js'][349]++; + return crc16(JSON.stringify(sess, (function (key, val) { + _$jscoverage['middleware/session.js'][350]++; + if ("cookie" != key) { + _$jscoverage['middleware/session.js'][350]++; + return val; + } +}))); +} +_$jscoverage['middleware/session.js'].source = ["","/*!"," * Connect - session"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var Session = require('./session/session')"," , debug = require('debug')('connect:session')"," , MemoryStore = require('./session/memory')"," , signature = require('cookie-signature')"," , Cookie = require('./session/cookie')"," , Store = require('./session/store')"," , utils = require('./../utils')"," , parse = utils.parseUrl"," , crc16 = require('crc').crc16;","","// environment","","var env = process.env.NODE_ENV;","","/**"," * Expose the middleware."," */","","exports = module.exports = session;","","/**"," * Expose constructors."," */","","exports.Store = Store;","exports.Cookie = Cookie;","exports.Session = Session;","exports.MemoryStore = MemoryStore;","","/**"," * Warning message for `MemoryStore` usage in production."," */","","var warning = 'Warning: connection.session() MemoryStore is not\\n'"," + 'designed for a production environment, as it will leak\\n'"," + 'memory, and will not scale past a single process.';","","/**"," * Session:"," * "," * Setup session store with the given `options`."," *"," * Session data is _not_ saved in the cookie itself, however"," * cookies are used, so we must use the [cookieParser()](cookieParser.html)"," * middleware _before_ `session()`."," *"," * Examples:"," *"," * connect()"," * .use(connect.cookieParser())"," * .use(connect.session({ secret: 'keyboard cat', key: 'sid', cookie: { secure: true }}))"," *"," * Options:"," *"," * - `key` cookie name defaulting to `connect.sid`"," * - `store` session store instance"," * - `secret` session cookie is signed with this secret to prevent tampering"," * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }`"," * - `proxy` trust the reverse proxy when setting secure cookies (via \"x-forwarded-proto\")"," *"," * Cookie option:"," *"," * By default `cookie.maxAge` is `null`, meaning no \"expires\" parameter is set"," * so the cookie becomes a browser-session cookie. When the user closes the "," * browser the cookie (and session) will be removed."," *"," * ## req.session"," *"," * To store or access session data, simply use the request property `req.session`,"," * which is (generally) serialized as JSON by the store, so nested objects "," * are typically fine. For example below is a user-specific view counter:"," *"," * connect()"," * .use(connect.favicon())"," * .use(connect.cookieParser())"," * .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))"," * .use(function(req, res, next){"," * var sess = req.session;"," * if (sess.views) {"," * res.setHeader('Content-Type', 'text/html');"," * res.write('<p>views: ' + sess.views + '</p>');"," * res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');"," * res.end();"," * sess.views++;"," * } else {"," * sess.views = 1;"," * res.end('welcome to the session demo. refresh!');"," * }"," * }"," * )).listen(3000);"," *"," * ## Session#regenerate()"," *"," * To regenerate the session simply invoke the method, once complete"," * a new SID and `Session` instance will be initialized at `req.session`."," *"," * req.session.regenerate(function(err){"," * // will have a new session here"," * });"," *"," * ## Session#destroy()"," *"," * Destroys the session, removing `req.session`, will be re-generated next request."," *"," * req.session.destroy(function(err){"," * // cannot access session here"," * });"," * "," * ## Session#reload()"," *"," * Reloads the session data."," *"," * req.session.reload(function(err){"," * // session updated"," * });"," *"," * ## Session#save()"," *"," * Save the session."," *"," * req.session.save(function(err){"," * // session saved"," * });"," *"," * ## Session#touch()"," *"," * Updates the `.maxAge` property. Typically this is"," * not necessary to call, as the session middleware does this for you."," *"," * ## Session#cookie"," *"," * Each session has a unique cookie object accompany it. This allows"," * you to alter the session cookie per visitor. For example we can"," * set `req.session.cookie.expires` to `false` to enable the cookie"," * to remain for only the duration of the user-agent."," *"," * ## Session#maxAge"," *"," * Alternatively `req.session.cookie.maxAge` will return the time"," * remaining in milliseconds, which we may also re-assign a new value"," * to adjust the `.expires` property appropriately. The following"," * are essentially equivalent"," *"," * var hour = 3600000;"," * req.session.cookie.expires = new Date(Date.now() + hour);"," * req.session.cookie.maxAge = hour;"," *"," * For example when `maxAge` is set to `60000` (one minute), and 30 seconds"," * has elapsed it will return `30000` until the current request has completed,"," * at which time `req.session.touch()` is called to reset `req.session.maxAge`"," * to its original value."," *"," * req.session.cookie.maxAge;"," * // => 30000"," *"," * Session Store Implementation:"," *"," * Every session store _must_ implement the following methods"," *"," * - `.get(sid, callback)`"," * - `.set(sid, session, callback)`"," * - `.destroy(sid, callback)`"," *"," * Recommended methods include, but are not limited to:"," *"," * - `.length(callback)`"," * - `.clear(callback)`"," *"," * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo."," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","function session(options){"," var options = options || {}"," , key = options.key || 'connect.sid'"," , store = options.store || new MemoryStore"," , cookie = options.cookie || {}"," , trustProxy = options.proxy"," , storeReady = true;",""," // notify user that this store is not"," // meant for a production environment"," if ('production' == env && store instanceof MemoryStore) {"," console.warn(warning);"," }",""," // generates the new session"," store.generate = function(req){"," req.sessionID = utils.uid(24);"," req.session = new Session(req);"," req.session.cookie = new Cookie(cookie);"," };",""," store.on('disconnect', function(){ storeReady = false; });"," store.on('connect', function(){ storeReady = true; });",""," return function session(req, res, next) {"," // self-awareness"," if (req.session) return next();",""," // Handle connection as if there is no session if"," // the store has temporarily disconnected etc"," if (!storeReady) return debug('store is disconnected'), next();",""," // pathname mismatch"," if (0 != req.originalUrl.indexOf(cookie.path || '/')) return next();",""," // backwards compatibility for signed cookies"," // req.secret is passed from the cookie parser middleware"," var secret = options.secret || req.secret;",""," // ensure secret is available or bail"," if (!secret) throw new Error('`secret` option required for sessions');",""," // parse url"," var originalHash"," , originalId;",""," // expose store"," req.sessionStore = store;",""," // grab the session cookie value and check the signature"," var rawCookie = req.cookies[key];",""," // get signedCookies for backwards compat with signed cookies"," var unsignedCookie = req.signedCookies[key];",""," if (!unsignedCookie && rawCookie) {"," unsignedCookie = utils.parseSignedCookie(rawCookie, secret);"," }",""," // set-cookie"," res.on('header', function(){"," if (!req.session) return;"," var cookie = req.session.cookie"," , proto = (req.headers['x-forwarded-proto'] || '').toLowerCase()"," , tls = req.connection.encrypted || (trustProxy && 'https' == proto)"," , secured = cookie.secure && tls"," , isNew = unsignedCookie != req.sessionID;",""," // only send secure cookies via https"," if (cookie.secure && !secured) return debug('not secured');",""," // browser-session length cookie"," if (null == cookie.expires) {"," if (!isNew) return debug('already set browser-session cookie');"," // compare hashes and ids"," } else if (originalHash == hash(req.session) && originalId == req.session.id) {"," return debug('unmodified session');"," }",""," var val = 's:' + signature.sign(req.sessionID, secret);"," val = cookie.serialize(key, val);"," debug('set-cookie %s', val);"," res.setHeader('Set-Cookie', val);"," });",""," // proxy end() to commit the session"," var end = res.end;"," res.end = function(data, encoding){"," res.end = end;"," if (!req.session) return res.end(data, encoding);"," debug('saving');"," req.session.resetMaxAge();"," req.session.save(function(){"," debug('saved');"," res.end(data, encoding);"," });"," };",""," // generate the session"," function generate() {"," store.generate(req);"," }",""," // get the sessionID from the cookie"," req.sessionID = unsignedCookie;",""," // generate a session if the browser doesn't send a sessionID"," if (!req.sessionID) {"," debug('no SID sent, generating session');"," generate();"," next();"," return;"," }",""," // generate the session object"," var pause = utils.pause(req);"," debug('fetching %s', req.sessionID);"," store.get(req.sessionID, function(err, sess){"," // proxy to resume() events"," var _next = next;"," next = function(err){"," _next(err);"," pause.resume();"," };",""," // error handling"," if (err) {"," debug('error');"," if ('ENOENT' == err.code) {"," generate();"," next();"," } else {"," next(err);"," }"," // no session"," } else if (!sess) {"," debug('no session found');"," generate();"," next();"," // populate req.session"," } else {"," debug('session found');"," store.createSession(req, sess);"," originalId = req.sessionID;"," originalHash = hash(sess);"," next();"," }"," });"," };","};","","/**"," * Hash the given `sess` object omitting changes"," * to `.cookie`."," *"," * @param {Object} sess"," * @return {String}"," * @api private"," */","","function hash(sess) {"," return crc16(JSON.stringify(sess, function(key, val){"," if ('cookie' != key) return val;"," }));","}"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/session/cookie.js b/node_modules/express/node_modules/connect/lib-cov/middleware/session/cookie.js new file mode 100644 index 0000000..279afe5 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/session/cookie.js @@ -0,0 +1,65 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/session/cookie.js']) { + _$jscoverage['middleware/session/cookie.js'] = []; + _$jscoverage['middleware/session/cookie.js'][13] = 0; + _$jscoverage['middleware/session/cookie.js'][24] = 0; + _$jscoverage['middleware/session/cookie.js'][25] = 0; + _$jscoverage['middleware/session/cookie.js'][26] = 0; + _$jscoverage['middleware/session/cookie.js'][27] = 0; + _$jscoverage['middleware/session/cookie.js'][28] = 0; + _$jscoverage['middleware/session/cookie.js'][29] = 0; + _$jscoverage['middleware/session/cookie.js'][38] = 0; + _$jscoverage['middleware/session/cookie.js'][48] = 0; + _$jscoverage['middleware/session/cookie.js'][49] = 0; + _$jscoverage['middleware/session/cookie.js'][60] = 0; + _$jscoverage['middleware/session/cookie.js'][71] = 0; + _$jscoverage['middleware/session/cookie.js'][84] = 0; + _$jscoverage['middleware/session/cookie.js'][97] = 0; + _$jscoverage['middleware/session/cookie.js'][115] = 0; + _$jscoverage['middleware/session/cookie.js'][126] = 0; +} +_$jscoverage['middleware/session/cookie.js'][13]++; +var utils = require("../../utils"), cookie = require("cookie"); +_$jscoverage['middleware/session/cookie.js'][24]++; +var Cookie = module.exports = (function Cookie(options) { + _$jscoverage['middleware/session/cookie.js'][25]++; + this.path = "/"; + _$jscoverage['middleware/session/cookie.js'][26]++; + this.maxAge = null; + _$jscoverage['middleware/session/cookie.js'][27]++; + this.httpOnly = true; + _$jscoverage['middleware/session/cookie.js'][28]++; + if (options) { + _$jscoverage['middleware/session/cookie.js'][28]++; + utils.merge(this, options); + } + _$jscoverage['middleware/session/cookie.js'][29]++; + this.originalMaxAge = undefined == this.originalMaxAge? this.maxAge: this.originalMaxAge; +}); +_$jscoverage['middleware/session/cookie.js'][38]++; +Cookie.prototype = {set expires (date) { + _$jscoverage['middleware/session/cookie.js'][48]++; + this._expires = date; + _$jscoverage['middleware/session/cookie.js'][49]++; + this.originalMaxAge = this.maxAge; +}, get expires () { + _$jscoverage['middleware/session/cookie.js'][60]++; + return this._expires; +}, set maxAge (ms) { + _$jscoverage['middleware/session/cookie.js'][71]++; + this.expires = "number" == typeof ms? new Date(Date.now() + ms): ms; +}, get maxAge () { + _$jscoverage['middleware/session/cookie.js'][84]++; + return this.expires instanceof Date? this.expires.valueOf() - Date.now(): this.expires; +}, get data () { + _$jscoverage['middleware/session/cookie.js'][97]++; + return ({originalMaxAge: this.originalMaxAge, expires: this._expires, secure: this.secure, httpOnly: this.httpOnly, domain: this.domain, path: this.path}); +}, serialize: (function (name, val) { + _$jscoverage['middleware/session/cookie.js'][115]++; + return cookie.serialize(name, val, this.data); +}), toJSON: (function () { + _$jscoverage['middleware/session/cookie.js'][126]++; + return this.data; +})}; +_$jscoverage['middleware/session/cookie.js'].source = ["","/*!"," * Connect - session - Cookie"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../../utils')"," , cookie = require('cookie');","","/**"," * Initialize a new `Cookie` with the given `options`."," *"," * @param {IncomingMessage} req"," * @param {Object} options"," * @api private"," */","","var Cookie = module.exports = function Cookie(options) {"," this.path = '/';"," this.maxAge = null;"," this.httpOnly = true;"," if (options) utils.merge(this, options);"," this.originalMaxAge = undefined == this.originalMaxAge"," ? this.maxAge"," : this.originalMaxAge;","};","","/*!"," * Prototype."," */","","Cookie.prototype = {",""," /**"," * Set expires `date`."," *"," * @param {Date} date"," * @api public"," */"," "," set expires(date) {"," this._expires = date;"," this.originalMaxAge = this.maxAge;"," },",""," /**"," * Get expires `date`."," *"," * @return {Date}"," * @api public"," */",""," get expires() {"," return this._expires;"," },"," "," /**"," * Set expires via max-age in `ms`."," *"," * @param {Number} ms"," * @api public"," */"," "," set maxAge(ms) {"," this.expires = 'number' == typeof ms"," ? new Date(Date.now() + ms)"," : ms;"," },",""," /**"," * Get expires max-age in `ms`."," *"," * @return {Number}"," * @api public"," */",""," get maxAge() {"," return this.expires instanceof Date"," ? this.expires.valueOf() - Date.now()"," : this.expires;"," },",""," /**"," * Return cookie data object."," *"," * @return {Object}"," * @api private"," */",""," get data() {"," return {"," originalMaxAge: this.originalMaxAge"," , expires: this._expires"," , secure: this.secure"," , httpOnly: this.httpOnly"," , domain: this.domain"," , path: this.path"," }"," },",""," /**"," * Return a serialized cookie string."," *"," * @return {String}"," * @api public"," */",""," serialize: function(name, val){"," return cookie.serialize(name, val, this.data);"," },",""," /**"," * Return JSON representation of this cookie."," *"," * @return {Object}"," * @api private"," */"," "," toJSON: function(){"," return this.data;"," }","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/session/memory.js b/node_modules/express/node_modules/connect/lib-cov/middleware/session/memory.js new file mode 100644 index 0000000..f140187 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/session/memory.js @@ -0,0 +1,128 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/session/memory.js']) { + _$jscoverage['middleware/session/memory.js'] = []; + _$jscoverage['middleware/session/memory.js'][13] = 0; + _$jscoverage['middleware/session/memory.js'][21] = 0; + _$jscoverage['middleware/session/memory.js'][22] = 0; + _$jscoverage['middleware/session/memory.js'][29] = 0; + _$jscoverage['middleware/session/memory.js'][39] = 0; + _$jscoverage['middleware/session/memory.js'][40] = 0; + _$jscoverage['middleware/session/memory.js'][41] = 0; + _$jscoverage['middleware/session/memory.js'][42] = 0; + _$jscoverage['middleware/session/memory.js'][44] = 0; + _$jscoverage['middleware/session/memory.js'][45] = 0; + _$jscoverage['middleware/session/memory.js'][46] = 0; + _$jscoverage['middleware/session/memory.js'][49] = 0; + _$jscoverage['middleware/session/memory.js'][50] = 0; + _$jscoverage['middleware/session/memory.js'][52] = 0; + _$jscoverage['middleware/session/memory.js'][55] = 0; + _$jscoverage['middleware/session/memory.js'][69] = 0; + _$jscoverage['middleware/session/memory.js'][70] = 0; + _$jscoverage['middleware/session/memory.js'][71] = 0; + _$jscoverage['middleware/session/memory.js'][72] = 0; + _$jscoverage['middleware/session/memory.js'][73] = 0; + _$jscoverage['middleware/session/memory.js'][84] = 0; + _$jscoverage['middleware/session/memory.js'][85] = 0; + _$jscoverage['middleware/session/memory.js'][86] = 0; + _$jscoverage['middleware/session/memory.js'][87] = 0; + _$jscoverage['middleware/session/memory.js'][88] = 0; + _$jscoverage['middleware/session/memory.js'][99] = 0; + _$jscoverage['middleware/session/memory.js'][100] = 0; + _$jscoverage['middleware/session/memory.js'][102] = 0; + _$jscoverage['middleware/session/memory.js'][103] = 0; + _$jscoverage['middleware/session/memory.js'][105] = 0; + _$jscoverage['middleware/session/memory.js'][115] = 0; + _$jscoverage['middleware/session/memory.js'][116] = 0; + _$jscoverage['middleware/session/memory.js'][117] = 0; + _$jscoverage['middleware/session/memory.js'][127] = 0; + _$jscoverage['middleware/session/memory.js'][128] = 0; +} +_$jscoverage['middleware/session/memory.js'][13]++; +var Store = require("./store"); +_$jscoverage['middleware/session/memory.js'][21]++; +var MemoryStore = module.exports = (function MemoryStore() { + _$jscoverage['middleware/session/memory.js'][22]++; + this.sessions = {}; +}); +_$jscoverage['middleware/session/memory.js'][29]++; +MemoryStore.prototype.__proto__ = Store.prototype; +_$jscoverage['middleware/session/memory.js'][39]++; +MemoryStore.prototype.get = (function (sid, fn) { + _$jscoverage['middleware/session/memory.js'][40]++; + var self = this; + _$jscoverage['middleware/session/memory.js'][41]++; + process.nextTick((function () { + _$jscoverage['middleware/session/memory.js'][42]++; + var expires, sess = self.sessions[sid]; + _$jscoverage['middleware/session/memory.js'][44]++; + if (sess) { + _$jscoverage['middleware/session/memory.js'][45]++; + sess = JSON.parse(sess); + _$jscoverage['middleware/session/memory.js'][46]++; + expires = "string" == typeof sess.cookie.expires? new Date(sess.cookie.expires): sess.cookie.expires; + _$jscoverage['middleware/session/memory.js'][49]++; + if (! expires || new Date() < expires) { + _$jscoverage['middleware/session/memory.js'][50]++; + fn(null, sess); + } + else { + _$jscoverage['middleware/session/memory.js'][52]++; + self.destroy(sid, fn); + } + } + else { + _$jscoverage['middleware/session/memory.js'][55]++; + fn(); + } +})); +}); +_$jscoverage['middleware/session/memory.js'][69]++; +MemoryStore.prototype.set = (function (sid, sess, fn) { + _$jscoverage['middleware/session/memory.js'][70]++; + var self = this; + _$jscoverage['middleware/session/memory.js'][71]++; + process.nextTick((function () { + _$jscoverage['middleware/session/memory.js'][72]++; + self.sessions[sid] = JSON.stringify(sess); + _$jscoverage['middleware/session/memory.js'][73]++; + fn && fn(); +})); +}); +_$jscoverage['middleware/session/memory.js'][84]++; +MemoryStore.prototype.destroy = (function (sid, fn) { + _$jscoverage['middleware/session/memory.js'][85]++; + var self = this; + _$jscoverage['middleware/session/memory.js'][86]++; + process.nextTick((function () { + _$jscoverage['middleware/session/memory.js'][87]++; + delete self.sessions[sid]; + _$jscoverage['middleware/session/memory.js'][88]++; + fn && fn(); +})); +}); +_$jscoverage['middleware/session/memory.js'][99]++; +MemoryStore.prototype.all = (function (fn) { + _$jscoverage['middleware/session/memory.js'][100]++; + var arr = [], keys = Object.keys(this.sessions); + _$jscoverage['middleware/session/memory.js'][102]++; + for (var i = 0, len = keys.length; i < len; ++i) { + _$jscoverage['middleware/session/memory.js'][103]++; + arr.push(this.sessions[keys[i]]); +} + _$jscoverage['middleware/session/memory.js'][105]++; + fn(null, arr); +}); +_$jscoverage['middleware/session/memory.js'][115]++; +MemoryStore.prototype.clear = (function (fn) { + _$jscoverage['middleware/session/memory.js'][116]++; + this.sessions = {}; + _$jscoverage['middleware/session/memory.js'][117]++; + fn && fn(); +}); +_$jscoverage['middleware/session/memory.js'][127]++; +MemoryStore.prototype.length = (function (fn) { + _$jscoverage['middleware/session/memory.js'][128]++; + fn(null, Object.keys(this.sessions).length); +}); +_$jscoverage['middleware/session/memory.js'].source = ["","/*!"," * Connect - session - MemoryStore"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var Store = require('./store');","","/**"," * Initialize a new `MemoryStore`."," *"," * @api public"," */","","var MemoryStore = module.exports = function MemoryStore() {"," this.sessions = {};","};","","/**"," * Inherit from `Store.prototype`."," */","","MemoryStore.prototype.__proto__ = Store.prototype;","","/**"," * Attempt to fetch session by the given `sid`."," *"," * @param {String} sid"," * @param {Function} fn"," * @api public"," */","","MemoryStore.prototype.get = function(sid, fn){"," var self = this;"," process.nextTick(function(){"," var expires"," , sess = self.sessions[sid];"," if (sess) {"," sess = JSON.parse(sess);"," expires = 'string' == typeof sess.cookie.expires"," ? new Date(sess.cookie.expires)"," : sess.cookie.expires;"," if (!expires || new Date < expires) {"," fn(null, sess);"," } else {"," self.destroy(sid, fn);"," }"," } else {"," fn();"," }"," });","};","","/**"," * Commit the given `sess` object associated with the given `sid`."," *"," * @param {String} sid"," * @param {Session} sess"," * @param {Function} fn"," * @api public"," */","","MemoryStore.prototype.set = function(sid, sess, fn){"," var self = this;"," process.nextTick(function(){"," self.sessions[sid] = JSON.stringify(sess);"," fn && fn();"," });","};","","/**"," * Destroy the session associated with the given `sid`."," *"," * @param {String} sid"," * @api public"," */","","MemoryStore.prototype.destroy = function(sid, fn){"," var self = this;"," process.nextTick(function(){"," delete self.sessions[sid];"," fn && fn();"," });","};","","/**"," * Invoke the given callback `fn` with all active sessions."," *"," * @param {Function} fn"," * @api public"," */","","MemoryStore.prototype.all = function(fn){"," var arr = []"," , keys = Object.keys(this.sessions);"," for (var i = 0, len = keys.length; i < len; ++i) {"," arr.push(this.sessions[keys[i]]);"," }"," fn(null, arr);","};","","/**"," * Clear all sessions."," *"," * @param {Function} fn"," * @api public"," */","","MemoryStore.prototype.clear = function(fn){"," this.sessions = {};"," fn && fn();","};","","/**"," * Fetch number of sessions."," *"," * @param {Function} fn"," * @api public"," */","","MemoryStore.prototype.length = function(fn){"," fn(null, Object.keys(this.sessions).length);","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/session/session.js b/node_modules/express/node_modules/connect/lib-cov/middleware/session/session.js new file mode 100644 index 0000000..73e85e0 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/session/session.js @@ -0,0 +1,108 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/session/session.js']) { + _$jscoverage['middleware/session/session.js'] = []; + _$jscoverage['middleware/session/session.js'][13] = 0; + _$jscoverage['middleware/session/session.js'][23] = 0; + _$jscoverage['middleware/session/session.js'][24] = 0; + _$jscoverage['middleware/session/session.js'][25] = 0; + _$jscoverage['middleware/session/session.js'][26] = 0; + _$jscoverage['middleware/session/session.js'][38] = 0; + _$jscoverage['middleware/session/session.js'][39] = 0; + _$jscoverage['middleware/session/session.js'][49] = 0; + _$jscoverage['middleware/session/session.js'][50] = 0; + _$jscoverage['middleware/session/session.js'][51] = 0; + _$jscoverage['middleware/session/session.js'][62] = 0; + _$jscoverage['middleware/session/session.js'][63] = 0; + _$jscoverage['middleware/session/session.js'][64] = 0; + _$jscoverage['middleware/session/session.js'][79] = 0; + _$jscoverage['middleware/session/session.js'][80] = 0; + _$jscoverage['middleware/session/session.js'][82] = 0; + _$jscoverage['middleware/session/session.js'][83] = 0; + _$jscoverage['middleware/session/session.js'][84] = 0; + _$jscoverage['middleware/session/session.js'][85] = 0; + _$jscoverage['middleware/session/session.js'][86] = 0; + _$jscoverage['middleware/session/session.js'][88] = 0; + _$jscoverage['middleware/session/session.js'][99] = 0; + _$jscoverage['middleware/session/session.js'][100] = 0; + _$jscoverage['middleware/session/session.js'][101] = 0; + _$jscoverage['middleware/session/session.js'][102] = 0; + _$jscoverage['middleware/session/session.js'][113] = 0; + _$jscoverage['middleware/session/session.js'][114] = 0; + _$jscoverage['middleware/session/session.js'][115] = 0; +} +_$jscoverage['middleware/session/session.js'][13]++; +var utils = require("../../utils"); +_$jscoverage['middleware/session/session.js'][23]++; +var Session = module.exports = (function Session(req, data) { + _$jscoverage['middleware/session/session.js'][24]++; + Object.defineProperty(this, "req", {value: req}); + _$jscoverage['middleware/session/session.js'][25]++; + Object.defineProperty(this, "id", {value: req.sessionID}); + _$jscoverage['middleware/session/session.js'][26]++; + if ("object" == typeof data) { + _$jscoverage['middleware/session/session.js'][26]++; + utils.merge(this, data); + } +}); +_$jscoverage['middleware/session/session.js'][38]++; +Session.prototype.touch = (function () { + _$jscoverage['middleware/session/session.js'][39]++; + return this.resetMaxAge(); +}); +_$jscoverage['middleware/session/session.js'][49]++; +Session.prototype.resetMaxAge = (function () { + _$jscoverage['middleware/session/session.js'][50]++; + this.cookie.maxAge = this.cookie.originalMaxAge; + _$jscoverage['middleware/session/session.js'][51]++; + return this; +}); +_$jscoverage['middleware/session/session.js'][62]++; +Session.prototype.save = (function (fn) { + _$jscoverage['middleware/session/session.js'][63]++; + this.req.sessionStore.set(this.id, this, fn || (function () { +})); + _$jscoverage['middleware/session/session.js'][64]++; + return this; +}); +_$jscoverage['middleware/session/session.js'][79]++; +Session.prototype.reload = (function (fn) { + _$jscoverage['middleware/session/session.js'][80]++; + var req = this.req, store = this.req.sessionStore; + _$jscoverage['middleware/session/session.js'][82]++; + store.get(this.id, (function (err, sess) { + _$jscoverage['middleware/session/session.js'][83]++; + if (err) { + _$jscoverage['middleware/session/session.js'][83]++; + return fn(err); + } + _$jscoverage['middleware/session/session.js'][84]++; + if (! sess) { + _$jscoverage['middleware/session/session.js'][84]++; + return fn(new Error("failed to load session")); + } + _$jscoverage['middleware/session/session.js'][85]++; + store.createSession(req, sess); + _$jscoverage['middleware/session/session.js'][86]++; + fn(); +})); + _$jscoverage['middleware/session/session.js'][88]++; + return this; +}); +_$jscoverage['middleware/session/session.js'][99]++; +Session.prototype.destroy = (function (fn) { + _$jscoverage['middleware/session/session.js'][100]++; + delete this.req.session; + _$jscoverage['middleware/session/session.js'][101]++; + this.req.sessionStore.destroy(this.id, fn); + _$jscoverage['middleware/session/session.js'][102]++; + return this; +}); +_$jscoverage['middleware/session/session.js'][113]++; +Session.prototype.regenerate = (function (fn) { + _$jscoverage['middleware/session/session.js'][114]++; + this.req.sessionStore.regenerate(this.req, fn); + _$jscoverage['middleware/session/session.js'][115]++; + return this; +}); +_$jscoverage['middleware/session/session.js'].source = ["","/*!"," * Connect - session - Session"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../../utils');","","/**"," * Create a new `Session` with the given request and `data`."," *"," * @param {IncomingRequest} req"," * @param {Object} data"," * @api private"," */","","var Session = module.exports = function Session(req, data) {"," Object.defineProperty(this, 'req', { value: req });"," Object.defineProperty(this, 'id', { value: req.sessionID });"," if ('object' == typeof data) utils.merge(this, data);","};","","/**"," * Update reset `.cookie.maxAge` to prevent"," * the cookie from expiring when the"," * session is still active."," *"," * @return {Session} for chaining"," * @api public"," */","","Session.prototype.touch = function(){"," return this.resetMaxAge();","};","","/**"," * Reset `.maxAge` to `.originalMaxAge`."," *"," * @return {Session} for chaining"," * @api public"," */","","Session.prototype.resetMaxAge = function(){"," this.cookie.maxAge = this.cookie.originalMaxAge;"," return this;","};","","/**"," * Save the session data with optional callback `fn(err)`."," *"," * @param {Function} fn"," * @return {Session} for chaining"," * @api public"," */","","Session.prototype.save = function(fn){"," this.req.sessionStore.set(this.id, this, fn || function(){});"," return this;","};","","/**"," * Re-loads the session data _without_ altering"," * the maxAge properties. Invokes the callback `fn(err)`,"," * after which time if no exception has occurred the"," * `req.session` property will be a new `Session` object,"," * although representing the same session."," *"," * @param {Function} fn"," * @return {Session} for chaining"," * @api public"," */","","Session.prototype.reload = function(fn){"," var req = this.req"," , store = this.req.sessionStore;"," store.get(this.id, function(err, sess){"," if (err) return fn(err);"," if (!sess) return fn(new Error('failed to load session'));"," store.createSession(req, sess);"," fn();"," });"," return this;","};","","/**"," * Destroy `this` session."," *"," * @param {Function} fn"," * @return {Session} for chaining"," * @api public"," */","","Session.prototype.destroy = function(fn){"," delete this.req.session;"," this.req.sessionStore.destroy(this.id, fn);"," return this;","};","","/**"," * Regenerate this request's session."," *"," * @param {Function} fn"," * @return {Session} for chaining"," * @api public"," */","","Session.prototype.regenerate = function(fn){"," this.req.sessionStore.regenerate(this.req, fn);"," return this;","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/session/store.js b/node_modules/express/node_modules/connect/lib-cov/middleware/session/store.js new file mode 100644 index 0000000..2d79aa2 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/session/store.js @@ -0,0 +1,90 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/session/store.js']) { + _$jscoverage['middleware/session/store.js'] = []; + _$jscoverage['middleware/session/store.js'][13] = 0; + _$jscoverage['middleware/session/store.js'][23] = 0; + _$jscoverage['middleware/session/store.js'][29] = 0; + _$jscoverage['middleware/session/store.js'][39] = 0; + _$jscoverage['middleware/session/store.js'][40] = 0; + _$jscoverage['middleware/session/store.js'][41] = 0; + _$jscoverage['middleware/session/store.js'][42] = 0; + _$jscoverage['middleware/session/store.js'][43] = 0; + _$jscoverage['middleware/session/store.js'][56] = 0; + _$jscoverage['middleware/session/store.js'][57] = 0; + _$jscoverage['middleware/session/store.js'][58] = 0; + _$jscoverage['middleware/session/store.js'][59] = 0; + _$jscoverage['middleware/session/store.js'][60] = 0; + _$jscoverage['middleware/session/store.js'][61] = 0; + _$jscoverage['middleware/session/store.js'][62] = 0; + _$jscoverage['middleware/session/store.js'][63] = 0; + _$jscoverage['middleware/session/store.js'][76] = 0; + _$jscoverage['middleware/session/store.js'][77] = 0; + _$jscoverage['middleware/session/store.js'][79] = 0; + _$jscoverage['middleware/session/store.js'][80] = 0; + _$jscoverage['middleware/session/store.js'][81] = 0; + _$jscoverage['middleware/session/store.js'][82] = 0; + _$jscoverage['middleware/session/store.js'][83] = 0; +} +_$jscoverage['middleware/session/store.js'][13]++; +var EventEmitter = require("events").EventEmitter, Session = require("./session"), Cookie = require("./cookie"); +_$jscoverage['middleware/session/store.js'][23]++; +var Store = module.exports = (function Store(options) { +}); +_$jscoverage['middleware/session/store.js'][29]++; +Store.prototype.__proto__ = EventEmitter.prototype; +_$jscoverage['middleware/session/store.js'][39]++; +Store.prototype.regenerate = (function (req, fn) { + _$jscoverage['middleware/session/store.js'][40]++; + var self = this; + _$jscoverage['middleware/session/store.js'][41]++; + this.destroy(req.sessionID, (function (err) { + _$jscoverage['middleware/session/store.js'][42]++; + self.generate(req); + _$jscoverage['middleware/session/store.js'][43]++; + fn(err); +})); +}); +_$jscoverage['middleware/session/store.js'][56]++; +Store.prototype.load = (function (sid, fn) { + _$jscoverage['middleware/session/store.js'][57]++; + var self = this; + _$jscoverage['middleware/session/store.js'][58]++; + this.get(sid, (function (err, sess) { + _$jscoverage['middleware/session/store.js'][59]++; + if (err) { + _$jscoverage['middleware/session/store.js'][59]++; + return fn(err); + } + _$jscoverage['middleware/session/store.js'][60]++; + if (! sess) { + _$jscoverage['middleware/session/store.js'][60]++; + return fn(); + } + _$jscoverage['middleware/session/store.js'][61]++; + var req = {sessionID: sid, sessionStore: self}; + _$jscoverage['middleware/session/store.js'][62]++; + sess = self.createSession(req, sess); + _$jscoverage['middleware/session/store.js'][63]++; + fn(null, sess); +})); +}); +_$jscoverage['middleware/session/store.js'][76]++; +Store.prototype.createSession = (function (req, sess) { + _$jscoverage['middleware/session/store.js'][77]++; + var expires = sess.cookie.expires, orig = sess.cookie.originalMaxAge; + _$jscoverage['middleware/session/store.js'][79]++; + sess.cookie = new Cookie(sess.cookie); + _$jscoverage['middleware/session/store.js'][80]++; + if ("string" == typeof expires) { + _$jscoverage['middleware/session/store.js'][80]++; + sess.cookie.expires = new Date(expires); + } + _$jscoverage['middleware/session/store.js'][81]++; + sess.cookie.originalMaxAge = orig; + _$jscoverage['middleware/session/store.js'][82]++; + req.session = new Session(req, sess); + _$jscoverage['middleware/session/store.js'][83]++; + return req.session; +}); +_$jscoverage['middleware/session/store.js'].source = ["","/*!"," * Connect - session - Store"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var EventEmitter = require('events').EventEmitter"," , Session = require('./session')"," , Cookie = require('./cookie');","","/**"," * Initialize abstract `Store`."," *"," * @api private"," */","","var Store = module.exports = function Store(options){};","","/**"," * Inherit from `EventEmitter.prototype`."," */","","Store.prototype.__proto__ = EventEmitter.prototype;","","/**"," * Re-generate the given requests's session."," *"," * @param {IncomingRequest} req"," * @return {Function} fn"," * @api public"," */","","Store.prototype.regenerate = function(req, fn){"," var self = this;"," this.destroy(req.sessionID, function(err){"," self.generate(req);"," fn(err);"," });","};","","/**"," * Load a `Session` instance via the given `sid`"," * and invoke the callback `fn(err, sess)`."," *"," * @param {String} sid"," * @param {Function} fn"," * @api public"," */","","Store.prototype.load = function(sid, fn){"," var self = this;"," this.get(sid, function(err, sess){"," if (err) return fn(err);"," if (!sess) return fn();"," var req = { sessionID: sid, sessionStore: self };"," sess = self.createSession(req, sess);"," fn(null, sess);"," });","};","","/**"," * Create session from JSON `sess` data."," *"," * @param {IncomingRequest} req"," * @param {Object} sess"," * @return {Session}"," * @api private"," */","","Store.prototype.createSession = function(req, sess){"," var expires = sess.cookie.expires"," , orig = sess.cookie.originalMaxAge;"," sess.cookie = new Cookie(sess.cookie);"," if ('string' == typeof expires) sess.cookie.expires = new Date(expires);"," sess.cookie.originalMaxAge = orig;"," req.session = new Session(req, sess);"," return req.session;","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/static.js b/node_modules/express/node_modules/connect/lib-cov/middleware/static.js new file mode 100644 index 0000000..c52b1c0 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/static.js @@ -0,0 +1,92 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/static.js']) { + _$jscoverage['middleware/static.js'] = []; + _$jscoverage['middleware/static.js'][13] = 0; + _$jscoverage['middleware/static.js'][45] = 0; + _$jscoverage['middleware/static.js'][46] = 0; + _$jscoverage['middleware/static.js'][49] = 0; + _$jscoverage['middleware/static.js'][52] = 0; + _$jscoverage['middleware/static.js'][54] = 0; + _$jscoverage['middleware/static.js'][55] = 0; + _$jscoverage['middleware/static.js'][56] = 0; + _$jscoverage['middleware/static.js'][57] = 0; + _$jscoverage['middleware/static.js'][59] = 0; + _$jscoverage['middleware/static.js'][60] = 0; + _$jscoverage['middleware/static.js'][61] = 0; + _$jscoverage['middleware/static.js'][64] = 0; + _$jscoverage['middleware/static.js'][65] = 0; + _$jscoverage['middleware/static.js'][66] = 0; + _$jscoverage['middleware/static.js'][67] = 0; + _$jscoverage['middleware/static.js'][68] = 0; + _$jscoverage['middleware/static.js'][69] = 0; + _$jscoverage['middleware/static.js'][72] = 0; + _$jscoverage['middleware/static.js'][73] = 0; + _$jscoverage['middleware/static.js'][74] = 0; + _$jscoverage['middleware/static.js'][77] = 0; + _$jscoverage['middleware/static.js'][94] = 0; +} +_$jscoverage['middleware/static.js'][13]++; +var send = require("send"), utils = require("../utils"), parse = utils.parseUrl, url = require("url"); +_$jscoverage['middleware/static.js'][45]++; +exports = module.exports = (function static(root, options) { + _$jscoverage['middleware/static.js'][46]++; + options = options || {}; + _$jscoverage['middleware/static.js'][49]++; + if (! root) { + _$jscoverage['middleware/static.js'][49]++; + throw new Error("static() root path required"); + } + _$jscoverage['middleware/static.js'][52]++; + var redirect = false !== options.redirect; + _$jscoverage['middleware/static.js'][54]++; + return (function static(req, res, next) { + _$jscoverage['middleware/static.js'][55]++; + if ("GET" != req.method && "HEAD" != req.method) { + _$jscoverage['middleware/static.js'][55]++; + return next(); + } + _$jscoverage['middleware/static.js'][56]++; + var path = parse(req).pathname; + _$jscoverage['middleware/static.js'][57]++; + var pause = utils.pause(req); + _$jscoverage['middleware/static.js'][59]++; + function resume() { + _$jscoverage['middleware/static.js'][60]++; + next(); + _$jscoverage['middleware/static.js'][61]++; + pause.resume(); +} + _$jscoverage['middleware/static.js'][64]++; + function directory() { + _$jscoverage['middleware/static.js'][65]++; + if (! redirect) { + _$jscoverage['middleware/static.js'][65]++; + return resume(); + } + _$jscoverage['middleware/static.js'][66]++; + var pathname = url.parse(req.originalUrl).pathname; + _$jscoverage['middleware/static.js'][67]++; + res.statusCode = 301; + _$jscoverage['middleware/static.js'][68]++; + res.setHeader("Location", pathname + "/"); + _$jscoverage['middleware/static.js'][69]++; + res.end("Redirecting to " + utils.escape(pathname) + "/"); +} + _$jscoverage['middleware/static.js'][72]++; + function error(err) { + _$jscoverage['middleware/static.js'][73]++; + if (404 == err.status) { + _$jscoverage['middleware/static.js'][73]++; + return resume(); + } + _$jscoverage['middleware/static.js'][74]++; + next(err); +} + _$jscoverage['middleware/static.js'][77]++; + send(req, path).maxage(options.maxAge || 0).root(root).hidden(options.hidden).on("error", error).on("directory", directory).pipe(res); +}); +}); +_$jscoverage['middleware/static.js'][94]++; +exports.mime = send.mime; +_$jscoverage['middleware/static.js'].source = ["","/*!"," * Connect - static"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var send = require('send')"," , utils = require('../utils')"," , parse = utils.parseUrl"," , url = require('url');","","/**"," * Static:"," *"," * Static file server with the given `root` path."," *"," * Examples:"," *"," * var oneDay = 86400000;"," *"," * connect()"," * .use(connect.static(__dirname + '/public'))"," *"," * connect()"," * .use(connect.static(__dirname + '/public', { maxAge: oneDay }))"," *"," * Options:"," *"," * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0"," * - `hidden` Allow transfer of hidden files. defaults to false"," * - `redirect` Redirect to trailing \"/\" when the pathname is a dir. defaults to true"," *"," * @param {String} root"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function static(root, options){"," options = options || {};",""," // root required"," if (!root) throw new Error('static() root path required');",""," // default redirect"," var redirect = false !== options.redirect;",""," return function static(req, res, next) {"," if ('GET' != req.method && 'HEAD' != req.method) return next();"," var path = parse(req).pathname;"," var pause = utils.pause(req);",""," function resume() {"," next();"," pause.resume();"," }",""," function directory() {"," if (!redirect) return resume();"," var pathname = url.parse(req.originalUrl).pathname;"," res.statusCode = 301;"," res.setHeader('Location', pathname + '/');"," res.end('Redirecting to ' + utils.escape(pathname) + '/');"," }",""," function error(err) {"," if (404 == err.status) return resume();"," next(err);"," }",""," send(req, path)"," .maxage(options.maxAge || 0)"," .root(root)"," .hidden(options.hidden)"," .on('error', error)"," .on('directory', directory)"," .pipe(res);"," };","};","","/**"," * Expose mime module."," * "," * If you wish to extend the mime table use this"," * reference to the \"mime\" module in the npm registry."," */","","exports.mime = send.mime;"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/staticCache.js b/node_modules/express/node_modules/connect/lib-cov/middleware/staticCache.js new file mode 100644 index 0000000..e8c2940 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/staticCache.js @@ -0,0 +1,276 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/staticCache.js']) { + _$jscoverage['middleware/staticCache.js'] = []; + _$jscoverage['middleware/staticCache.js'][12] = 0; + _$jscoverage['middleware/staticCache.js'][51] = 0; + _$jscoverage['middleware/staticCache.js'][52] = 0; + _$jscoverage['middleware/staticCache.js'][56] = 0; + _$jscoverage['middleware/staticCache.js'][57] = 0; + _$jscoverage['middleware/staticCache.js'][59] = 0; + _$jscoverage['middleware/staticCache.js'][60] = 0; + _$jscoverage['middleware/staticCache.js'][68] = 0; + _$jscoverage['middleware/staticCache.js'][69] = 0; + _$jscoverage['middleware/staticCache.js'][75] = 0; + _$jscoverage['middleware/staticCache.js'][78] = 0; + _$jscoverage['middleware/staticCache.js'][81] = 0; + _$jscoverage['middleware/staticCache.js'][84] = 0; + _$jscoverage['middleware/staticCache.js'][88] = 0; + _$jscoverage['middleware/staticCache.js'][91] = 0; + _$jscoverage['middleware/staticCache.js'][94] = 0; + _$jscoverage['middleware/staticCache.js'][95] = 0; + _$jscoverage['middleware/staticCache.js'][96] = 0; + _$jscoverage['middleware/staticCache.js'][97] = 0; + _$jscoverage['middleware/staticCache.js'][99] = 0; + _$jscoverage['middleware/staticCache.js'][104] = 0; + _$jscoverage['middleware/staticCache.js'][107] = 0; + _$jscoverage['middleware/staticCache.js'][110] = 0; + _$jscoverage['middleware/staticCache.js'][111] = 0; + _$jscoverage['middleware/staticCache.js'][115] = 0; + _$jscoverage['middleware/staticCache.js'][116] = 0; + _$jscoverage['middleware/staticCache.js'][117] = 0; + _$jscoverage['middleware/staticCache.js'][118] = 0; + _$jscoverage['middleware/staticCache.js'][119] = 0; + _$jscoverage['middleware/staticCache.js'][120] = 0; + _$jscoverage['middleware/staticCache.js'][124] = 0; + _$jscoverage['middleware/staticCache.js'][125] = 0; + _$jscoverage['middleware/staticCache.js'][126] = 0; + _$jscoverage['middleware/staticCache.js'][127] = 0; + _$jscoverage['middleware/staticCache.js'][128] = 0; + _$jscoverage['middleware/staticCache.js'][129] = 0; + _$jscoverage['middleware/staticCache.js'][131] = 0; + _$jscoverage['middleware/staticCache.js'][132] = 0; + _$jscoverage['middleware/staticCache.js'][135] = 0; + _$jscoverage['middleware/staticCache.js'][151] = 0; + _$jscoverage['middleware/staticCache.js'][152] = 0; + _$jscoverage['middleware/staticCache.js'][156] = 0; + _$jscoverage['middleware/staticCache.js'][158] = 0; + _$jscoverage['middleware/staticCache.js'][160] = 0; + _$jscoverage['middleware/staticCache.js'][161] = 0; + _$jscoverage['middleware/staticCache.js'][162] = 0; + _$jscoverage['middleware/staticCache.js'][164] = 0; + _$jscoverage['middleware/staticCache.js'][165] = 0; + _$jscoverage['middleware/staticCache.js'][166] = 0; + _$jscoverage['middleware/staticCache.js'][167] = 0; + _$jscoverage['middleware/staticCache.js'][169] = 0; + _$jscoverage['middleware/staticCache.js'][171] = 0; + _$jscoverage['middleware/staticCache.js'][172] = 0; + _$jscoverage['middleware/staticCache.js'][173] = 0; + _$jscoverage['middleware/staticCache.js'][174] = 0; + _$jscoverage['middleware/staticCache.js'][175] = 0; + _$jscoverage['middleware/staticCache.js'][178] = 0; + _$jscoverage['middleware/staticCache.js'][181] = 0; + _$jscoverage['middleware/staticCache.js'][183] = 0; + _$jscoverage['middleware/staticCache.js'][186] = 0; + _$jscoverage['middleware/staticCache.js'][187] = 0; + _$jscoverage['middleware/staticCache.js'][200] = 0; + _$jscoverage['middleware/staticCache.js'][201] = 0; + _$jscoverage['middleware/staticCache.js'][206] = 0; + _$jscoverage['middleware/staticCache.js'][208] = 0; + _$jscoverage['middleware/staticCache.js'][210] = 0; + _$jscoverage['middleware/staticCache.js'][212] = 0; + _$jscoverage['middleware/staticCache.js'][214] = 0; + _$jscoverage['middleware/staticCache.js'][216] = 0; + _$jscoverage['middleware/staticCache.js'][229] = 0; + _$jscoverage['middleware/staticCache.js'][230] = 0; +} +_$jscoverage['middleware/staticCache.js'][12]++; +var utils = require("../utils"), Cache = require("../cache"), fresh = require("fresh"); +_$jscoverage['middleware/staticCache.js'][51]++; +module.exports = (function staticCache(options) { + _$jscoverage['middleware/staticCache.js'][52]++; + var options = options || {}, cache = new Cache(options.maxObjects || 128), maxlen = options.maxLength || 262144; + _$jscoverage['middleware/staticCache.js'][56]++; + console.warn("connect.staticCache() is deprecated and will be removed in 3.0"); + _$jscoverage['middleware/staticCache.js'][57]++; + console.warn("use varnish or similar reverse proxy caches."); + _$jscoverage['middleware/staticCache.js'][59]++; + return (function staticCache(req, res, next) { + _$jscoverage['middleware/staticCache.js'][60]++; + var key = cacheKey(req), ranges = req.headers.range, hasCookies = req.headers.cookie, hit = cache.get(key); + _$jscoverage['middleware/staticCache.js'][68]++; + req.on("static", (function (stream) { + _$jscoverage['middleware/staticCache.js'][69]++; + var headers = res._headers, cc = utils.parseCacheControl(headers["cache-control"] || ""), contentLength = headers["content-length"], hit; + _$jscoverage['middleware/staticCache.js'][75]++; + if (headers["set-cookie"]) { + _$jscoverage['middleware/staticCache.js'][75]++; + return hasCookies = true; + } + _$jscoverage['middleware/staticCache.js'][78]++; + if (hasCookies) { + _$jscoverage['middleware/staticCache.js'][78]++; + return; + } + _$jscoverage['middleware/staticCache.js'][81]++; + if (! contentLength || contentLength > maxlen) { + _$jscoverage['middleware/staticCache.js'][81]++; + return; + } + _$jscoverage['middleware/staticCache.js'][84]++; + if (headers["content-range"]) { + _$jscoverage['middleware/staticCache.js'][84]++; + return; + } + _$jscoverage['middleware/staticCache.js'][88]++; + if (cc["no-cache"] || cc["no-store"] || cc["private"] || cc["must-revalidate"]) { + _$jscoverage['middleware/staticCache.js'][91]++; + return; + } + _$jscoverage['middleware/staticCache.js'][94]++; + if (hit = cache.get(key)) { + _$jscoverage['middleware/staticCache.js'][95]++; + if (headers.etag == hit[0].etag) { + _$jscoverage['middleware/staticCache.js'][96]++; + hit[0].date = new Date(); + _$jscoverage['middleware/staticCache.js'][97]++; + return; + } + else { + _$jscoverage['middleware/staticCache.js'][99]++; + cache.remove(key); + } + } + _$jscoverage['middleware/staticCache.js'][104]++; + if (null == stream) { + _$jscoverage['middleware/staticCache.js'][104]++; + return; + } + _$jscoverage['middleware/staticCache.js'][107]++; + var arr = []; + _$jscoverage['middleware/staticCache.js'][110]++; + stream.on("data", (function (chunk) { + _$jscoverage['middleware/staticCache.js'][111]++; + arr.push(chunk); +})); + _$jscoverage['middleware/staticCache.js'][115]++; + stream.on("end", (function () { + _$jscoverage['middleware/staticCache.js'][116]++; + var cacheEntry = cache.add(key); + _$jscoverage['middleware/staticCache.js'][117]++; + delete headers["x-cache"]; + _$jscoverage['middleware/staticCache.js'][118]++; + cacheEntry.push(200); + _$jscoverage['middleware/staticCache.js'][119]++; + cacheEntry.push(headers); + _$jscoverage['middleware/staticCache.js'][120]++; + cacheEntry.push.apply(cacheEntry, arr); +})); +})); + _$jscoverage['middleware/staticCache.js'][124]++; + if (req.method == "GET" || req.method == "HEAD") { + _$jscoverage['middleware/staticCache.js'][125]++; + if (ranges) { + _$jscoverage['middleware/staticCache.js'][126]++; + next(); + } + else { + _$jscoverage['middleware/staticCache.js'][127]++; + if (! hasCookies && hit && ! mustRevalidate(req, hit)) { + _$jscoverage['middleware/staticCache.js'][128]++; + res.setHeader("X-Cache", "HIT"); + _$jscoverage['middleware/staticCache.js'][129]++; + respondFromCache(req, res, hit); + } + else { + _$jscoverage['middleware/staticCache.js'][131]++; + res.setHeader("X-Cache", "MISS"); + _$jscoverage['middleware/staticCache.js'][132]++; + next(); + } + } + } + else { + _$jscoverage['middleware/staticCache.js'][135]++; + next(); + } +}); +}); +_$jscoverage['middleware/staticCache.js'][151]++; +function respondFromCache(req, res, cacheEntry) { + _$jscoverage['middleware/staticCache.js'][152]++; + var status = cacheEntry[0], headers = utils.merge({}, cacheEntry[1]), content = cacheEntry.slice(2); + _$jscoverage['middleware/staticCache.js'][156]++; + headers.age = (new Date() - new Date(headers.date)) / 1000 || 0; + _$jscoverage['middleware/staticCache.js'][158]++; + switch (req.method) { + case "HEAD": + _$jscoverage['middleware/staticCache.js'][160]++; + res.writeHead(status, headers); + _$jscoverage['middleware/staticCache.js'][161]++; + res.end(); + _$jscoverage['middleware/staticCache.js'][162]++; + break; + case "GET": + _$jscoverage['middleware/staticCache.js'][164]++; + if (utils.conditionalGET(req) && fresh(req.headers, headers)) { + _$jscoverage['middleware/staticCache.js'][165]++; + headers["content-length"] = 0; + _$jscoverage['middleware/staticCache.js'][166]++; + res.writeHead(304, headers); + _$jscoverage['middleware/staticCache.js'][167]++; + res.end(); + } + else { + _$jscoverage['middleware/staticCache.js'][169]++; + res.writeHead(status, headers); + _$jscoverage['middleware/staticCache.js'][171]++; + function write() { + _$jscoverage['middleware/staticCache.js'][172]++; + while (content.length) { + _$jscoverage['middleware/staticCache.js'][173]++; + if (false === res.write(content.shift())) { + _$jscoverage['middleware/staticCache.js'][174]++; + res.once("drain", write); + _$jscoverage['middleware/staticCache.js'][175]++; + return; + } +} + _$jscoverage['middleware/staticCache.js'][178]++; + res.end(); +} + _$jscoverage['middleware/staticCache.js'][181]++; + write(); + } + _$jscoverage['middleware/staticCache.js'][183]++; + break; + default: + _$jscoverage['middleware/staticCache.js'][186]++; + res.writeHead(500, ""); + _$jscoverage['middleware/staticCache.js'][187]++; + res.end(); + } +} +_$jscoverage['middleware/staticCache.js'][200]++; +function mustRevalidate(req, cacheEntry) { + _$jscoverage['middleware/staticCache.js'][201]++; + var cacheHeaders = cacheEntry[1], reqCC = utils.parseCacheControl(req.headers["cache-control"] || ""), cacheCC = utils.parseCacheControl(cacheHeaders["cache-control"] || ""), cacheAge = (new Date() - new Date(cacheHeaders.date)) / 1000 || 0; + _$jscoverage['middleware/staticCache.js'][206]++; + if (cacheCC["no-cache"] || cacheCC["must-revalidate"] || cacheCC["proxy-revalidate"]) { + _$jscoverage['middleware/staticCache.js'][208]++; + return true; + } + _$jscoverage['middleware/staticCache.js'][210]++; + if (reqCC["no-cache"]) { + _$jscoverage['middleware/staticCache.js'][210]++; + return true; + } + _$jscoverage['middleware/staticCache.js'][212]++; + if (null != reqCC["max-age"]) { + _$jscoverage['middleware/staticCache.js'][212]++; + return reqCC["max-age"] < cacheAge; + } + _$jscoverage['middleware/staticCache.js'][214]++; + if (null != cacheCC["max-age"]) { + _$jscoverage['middleware/staticCache.js'][214]++; + return cacheCC["max-age"] < cacheAge; + } + _$jscoverage['middleware/staticCache.js'][216]++; + return false; +} +_$jscoverage['middleware/staticCache.js'][229]++; +function cacheKey(req) { + _$jscoverage['middleware/staticCache.js'][230]++; + return utils.parseUrl(req).path; +} +_$jscoverage['middleware/staticCache.js'].source = ["","/*!"," * Connect - staticCache"," * Copyright(c) 2011 Sencha Inc."," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils')"," , Cache = require('../cache')"," , fresh = require('fresh');","","/**"," * Static cache:"," *"," * Enables a memory cache layer on top of"," * the `static()` middleware, serving popular"," * static files."," *"," * By default a maximum of 128 objects are"," * held in cache, with a max of 256k each,"," * totalling ~32mb."," *"," * A Least-Recently-Used (LRU) cache algo"," * is implemented through the `Cache` object,"," * simply rotating cache objects as they are"," * hit. This means that increasingly popular"," * objects maintain their positions while"," * others get shoved out of the stack and"," * garbage collected."," *"," * Benchmarks:"," *"," * static(): 2700 rps"," * node-static: 5300 rps"," * static() + staticCache(): 7500 rps"," *"," * Options:"," *"," * - `maxObjects` max cache objects [128]"," * - `maxLength` max cache object length 256kb"," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","module.exports = function staticCache(options){"," var options = options || {}"," , cache = new Cache(options.maxObjects || 128)"," , maxlen = options.maxLength || 1024 * 256;",""," console.warn('connect.staticCache() is deprecated and will be removed in 3.0');"," console.warn('use varnish or similar reverse proxy caches.');",""," return function staticCache(req, res, next){"," var key = cacheKey(req)"," , ranges = req.headers.range"," , hasCookies = req.headers.cookie"," , hit = cache.get(key);",""," // cache static"," // TODO: change from staticCache() -> cache()"," // and make this work for any request"," req.on('static', function(stream){"," var headers = res._headers"," , cc = utils.parseCacheControl(headers['cache-control'] || '')"," , contentLength = headers['content-length']"," , hit;",""," // dont cache set-cookie responses"," if (headers['set-cookie']) return hasCookies = true;",""," // dont cache when cookies are present"," if (hasCookies) return;",""," // ignore larger files"," if (!contentLength || contentLength > maxlen) return;",""," // don't cache partial files"," if (headers['content-range']) return;",""," // dont cache items we shouldn't be"," // TODO: real support for must-revalidate / no-cache"," if ( cc['no-cache']"," || cc['no-store']"," || cc['private']"," || cc['must-revalidate']) return;",""," // if already in cache then validate"," if (hit = cache.get(key)){"," if (headers.etag == hit[0].etag) {"," hit[0].date = new Date;"," return;"," } else {"," cache.remove(key);"," }"," }",""," // validation notifiactions don't contain a steam"," if (null == stream) return;",""," // add the cache object"," var arr = [];",""," // store the chunks"," stream.on('data', function(chunk){"," arr.push(chunk);"," });",""," // flag it as complete"," stream.on('end', function(){"," var cacheEntry = cache.add(key);"," delete headers['x-cache']; // Clean up (TODO: others)"," cacheEntry.push(200);"," cacheEntry.push(headers);"," cacheEntry.push.apply(cacheEntry, arr);"," });"," });",""," if (req.method == 'GET' || req.method == 'HEAD') {"," if (ranges) {"," next();"," } else if (!hasCookies && hit && !mustRevalidate(req, hit)) {"," res.setHeader('X-Cache', 'HIT');"," respondFromCache(req, res, hit);"," } else {"," res.setHeader('X-Cache', 'MISS');"," next();"," }"," } else {"," next();"," }"," }","};","","/**"," * Respond with the provided cached value."," * TODO: Assume 200 code, that's iffy."," *"," * @param {Object} req"," * @param {Object} res"," * @param {Object} cacheEntry"," * @return {String}"," * @api private"," */","","function respondFromCache(req, res, cacheEntry) {"," var status = cacheEntry[0]"," , headers = utils.merge({}, cacheEntry[1])"," , content = cacheEntry.slice(2);",""," headers.age = (new Date - new Date(headers.date)) / 1000 || 0;",""," switch (req.method) {"," case 'HEAD':"," res.writeHead(status, headers);"," res.end();"," break;"," case 'GET':"," if (utils.conditionalGET(req) && fresh(req.headers, headers)) {"," headers['content-length'] = 0;"," res.writeHead(304, headers);"," res.end();"," } else {"," res.writeHead(status, headers);",""," function write() {"," while (content.length) {"," if (false === res.write(content.shift())) {"," res.once('drain', write);"," return;"," }"," }"," res.end();"," }",""," write();"," }"," break;"," default:"," // This should never happen."," res.writeHead(500, '');"," res.end();"," }","}","","/**"," * Determine whether or not a cached value must be revalidated."," *"," * @param {Object} req"," * @param {Object} cacheEntry"," * @return {String}"," * @api private"," */","","function mustRevalidate(req, cacheEntry) {"," var cacheHeaders = cacheEntry[1]"," , reqCC = utils.parseCacheControl(req.headers['cache-control'] || '')"," , cacheCC = utils.parseCacheControl(cacheHeaders['cache-control'] || '')"," , cacheAge = (new Date - new Date(cacheHeaders.date)) / 1000 || 0;",""," if ( cacheCC['no-cache']"," || cacheCC['must-revalidate']"," || cacheCC['proxy-revalidate']) return true;",""," if (reqCC['no-cache']) return true;",""," if (null != reqCC['max-age']) return reqCC['max-age'] < cacheAge;",""," if (null != cacheCC['max-age']) return cacheCC['max-age'] < cacheAge;",""," return false;","}","","/**"," * The key to use in the cache. For now, this is the URL path and query."," *"," * 'http://example.com?key=value' -> '/?key=value'"," *"," * @param {Object} req"," * @return {String}"," * @api private"," */","","function cacheKey(req) {"," return utils.parseUrl(req).path;","}"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/timeout.js b/node_modules/express/node_modules/connect/lib-cov/middleware/timeout.js new file mode 100644 index 0000000..de0e573 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/timeout.js @@ -0,0 +1,66 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/timeout.js']) { + _$jscoverage['middleware/timeout.js'] = []; + _$jscoverage['middleware/timeout.js'][12] = 0; + _$jscoverage['middleware/timeout.js'][30] = 0; + _$jscoverage['middleware/timeout.js'][31] = 0; + _$jscoverage['middleware/timeout.js'][33] = 0; + _$jscoverage['middleware/timeout.js'][34] = 0; + _$jscoverage['middleware/timeout.js'][35] = 0; + _$jscoverage['middleware/timeout.js'][38] = 0; + _$jscoverage['middleware/timeout.js'][39] = 0; + _$jscoverage['middleware/timeout.js'][40] = 0; + _$jscoverage['middleware/timeout.js'][41] = 0; + _$jscoverage['middleware/timeout.js'][42] = 0; + _$jscoverage['middleware/timeout.js'][43] = 0; + _$jscoverage['middleware/timeout.js'][46] = 0; + _$jscoverage['middleware/timeout.js'][47] = 0; + _$jscoverage['middleware/timeout.js'][50] = 0; + _$jscoverage['middleware/timeout.js'][51] = 0; + _$jscoverage['middleware/timeout.js'][54] = 0; +} +_$jscoverage['middleware/timeout.js'][12]++; +var debug = require("debug")("connect:timeout"); +_$jscoverage['middleware/timeout.js'][30]++; +module.exports = (function timeout(ms) { + _$jscoverage['middleware/timeout.js'][31]++; + ms = ms || 5000; + _$jscoverage['middleware/timeout.js'][33]++; + return (function (req, res, next) { + _$jscoverage['middleware/timeout.js'][34]++; + var id = setTimeout((function () { + _$jscoverage['middleware/timeout.js'][35]++; + req.emit("timeout", ms); +}), ms); + _$jscoverage['middleware/timeout.js'][38]++; + req.on("timeout", (function () { + _$jscoverage['middleware/timeout.js'][39]++; + if (req.headerSent) { + _$jscoverage['middleware/timeout.js'][39]++; + return debug("response started, cannot timeout"); + } + _$jscoverage['middleware/timeout.js'][40]++; + var err = new Error("Request timeout"); + _$jscoverage['middleware/timeout.js'][41]++; + err.timeout = ms; + _$jscoverage['middleware/timeout.js'][42]++; + err.status = 408; + _$jscoverage['middleware/timeout.js'][43]++; + next(err); +})); + _$jscoverage['middleware/timeout.js'][46]++; + req.clearTimeout = (function () { + _$jscoverage['middleware/timeout.js'][47]++; + clearTimeout(id); +}); + _$jscoverage['middleware/timeout.js'][50]++; + res.on("header", (function () { + _$jscoverage['middleware/timeout.js'][51]++; + clearTimeout(id); +})); + _$jscoverage['middleware/timeout.js'][54]++; + next(); +}); +}); +_$jscoverage['middleware/timeout.js'].source = ["","/*!"," * Connect - timeout"," * Ported from https://github.com/LearnBoost/connect-timeout"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var debug = require('debug')('connect:timeout');","","/**"," * Timeout:"," *"," * Times out the request in `ms`, defaulting to `5000`. The"," * method `req.clearTimeout()` is added to revert this behaviour"," * programmatically within your application's middleware, routes, etc."," *"," * The timeout error is passed to `next()` so that you may customize"," * the response behaviour. This error has the `.timeout` property as"," * well as `.status == 408`."," *"," * @param {Number} ms"," * @return {Function}"," * @api public"," */","","module.exports = function timeout(ms) {"," ms = ms || 5000;",""," return function(req, res, next) {"," var id = setTimeout(function(){"," req.emit('timeout', ms);"," }, ms);",""," req.on('timeout', function(){"," if (req.headerSent) return debug('response started, cannot timeout');"," var err = new Error('Request timeout');"," err.timeout = ms;"," err.status = 408;"," next(err);"," });",""," req.clearTimeout = function(){"," clearTimeout(id);"," };",""," res.on('header', function(){"," clearTimeout(id);"," });",""," next();"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/urlencoded.js b/node_modules/express/node_modules/connect/lib-cov/middleware/urlencoded.js new file mode 100644 index 0000000..c8dbcef --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/urlencoded.js @@ -0,0 +1,98 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/urlencoded.js']) { + _$jscoverage['middleware/urlencoded.js'] = []; + _$jscoverage['middleware/urlencoded.js'][13] = 0; + _$jscoverage['middleware/urlencoded.js'][21] = 0; + _$jscoverage['middleware/urlencoded.js'][22] = 0; + _$jscoverage['middleware/urlencoded.js'][40] = 0; + _$jscoverage['middleware/urlencoded.js'][41] = 0; + _$jscoverage['middleware/urlencoded.js'][43] = 0; + _$jscoverage['middleware/urlencoded.js'][47] = 0; + _$jscoverage['middleware/urlencoded.js'][48] = 0; + _$jscoverage['middleware/urlencoded.js'][49] = 0; + _$jscoverage['middleware/urlencoded.js'][51] = 0; + _$jscoverage['middleware/urlencoded.js'][54] = 0; + _$jscoverage['middleware/urlencoded.js'][57] = 0; + _$jscoverage['middleware/urlencoded.js'][60] = 0; + _$jscoverage['middleware/urlencoded.js'][61] = 0; + _$jscoverage['middleware/urlencoded.js'][62] = 0; + _$jscoverage['middleware/urlencoded.js'][63] = 0; + _$jscoverage['middleware/urlencoded.js'][64] = 0; + _$jscoverage['middleware/urlencoded.js'][65] = 0; + _$jscoverage['middleware/urlencoded.js'][66] = 0; + _$jscoverage['middleware/urlencoded.js'][67] = 0; + _$jscoverage['middleware/urlencoded.js'][70] = 0; + _$jscoverage['middleware/urlencoded.js'][72] = 0; + _$jscoverage['middleware/urlencoded.js'][73] = 0; +} +_$jscoverage['middleware/urlencoded.js'][13]++; +var utils = require("../utils"), _limit = require("./limit"), qs = require("qs"); +_$jscoverage['middleware/urlencoded.js'][21]++; +function noop(req, res, next) { + _$jscoverage['middleware/urlencoded.js'][22]++; + next(); +} +_$jscoverage['middleware/urlencoded.js'][40]++; +exports = module.exports = (function (options) { + _$jscoverage['middleware/urlencoded.js'][41]++; + options = options || {}; + _$jscoverage['middleware/urlencoded.js'][43]++; + var limit = options.limit? _limit(options.limit): noop; + _$jscoverage['middleware/urlencoded.js'][47]++; + return (function urlencoded(req, res, next) { + _$jscoverage['middleware/urlencoded.js'][48]++; + if (req._body) { + _$jscoverage['middleware/urlencoded.js'][48]++; + return next(); + } + _$jscoverage['middleware/urlencoded.js'][49]++; + req.body = req.body || {}; + _$jscoverage['middleware/urlencoded.js'][51]++; + if (! utils.hasBody(req)) { + _$jscoverage['middleware/urlencoded.js'][51]++; + return next(); + } + _$jscoverage['middleware/urlencoded.js'][54]++; + if ("application/x-www-form-urlencoded" != utils.mime(req)) { + _$jscoverage['middleware/urlencoded.js'][54]++; + return next(); + } + _$jscoverage['middleware/urlencoded.js'][57]++; + req._body = true; + _$jscoverage['middleware/urlencoded.js'][60]++; + limit(req, res, (function (err) { + _$jscoverage['middleware/urlencoded.js'][61]++; + if (err) { + _$jscoverage['middleware/urlencoded.js'][61]++; + return next(err); + } + _$jscoverage['middleware/urlencoded.js'][62]++; + var buf = ""; + _$jscoverage['middleware/urlencoded.js'][63]++; + req.setEncoding("utf8"); + _$jscoverage['middleware/urlencoded.js'][64]++; + req.on("data", (function (chunk) { + _$jscoverage['middleware/urlencoded.js'][64]++; + buf += chunk; +})); + _$jscoverage['middleware/urlencoded.js'][65]++; + req.on("end", (function () { + _$jscoverage['middleware/urlencoded.js'][66]++; + try { + _$jscoverage['middleware/urlencoded.js'][67]++; + req.body = buf.length? qs.parse(buf, options): {}; + _$jscoverage['middleware/urlencoded.js'][70]++; + next(); + } + catch (err) { + _$jscoverage['middleware/urlencoded.js'][72]++; + err.body = buf; + _$jscoverage['middleware/urlencoded.js'][73]++; + next(err); + } +})); +})); +}); +}); +_$jscoverage['middleware/urlencoded.js'].source = ["","/*!"," * Connect - urlencoded"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var utils = require('../utils')"," , _limit = require('./limit')"," , qs = require('qs');","","/**"," * noop middleware."," */","","function noop(req, res, next) {"," next();","}","","/**"," * Urlencoded:"," * "," * Parse x-ww-form-urlencoded request bodies,"," * providing the parsed object as `req.body`."," *"," * Options:"," *"," * - `limit` byte limit disabled by default"," *"," * @param {Object} options"," * @return {Function}"," * @api public"," */","","exports = module.exports = function(options){"," options = options || {};",""," var limit = options.limit"," ? _limit(options.limit)"," : noop;",""," return function urlencoded(req, res, next) {"," if (req._body) return next();"," req.body = req.body || {};",""," if (!utils.hasBody(req)) return next();",""," // check Content-Type"," if ('application/x-www-form-urlencoded' != utils.mime(req)) return next();",""," // flag as parsed"," req._body = true;",""," // parse"," limit(req, res, function(err){"," if (err) return next(err);"," var buf = '';"," req.setEncoding('utf8');"," req.on('data', function(chunk){ buf += chunk });"," req.on('end', function(){"," try {"," req.body = buf.length"," ? qs.parse(buf, options)"," : {};"," next();"," } catch (err){"," err.body = buf;"," next(err);"," }"," });"," });"," }","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/middleware/vhost.js b/node_modules/express/node_modules/connect/lib-cov/middleware/vhost.js new file mode 100644 index 0000000..b069e5c --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/middleware/vhost.js @@ -0,0 +1,59 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['middleware/vhost.js']) { + _$jscoverage['middleware/vhost.js'] = []; + _$jscoverage['middleware/vhost.js'][28] = 0; + _$jscoverage['middleware/vhost.js'][29] = 0; + _$jscoverage['middleware/vhost.js'][30] = 0; + _$jscoverage['middleware/vhost.js'][31] = 0; + _$jscoverage['middleware/vhost.js'][32] = 0; + _$jscoverage['middleware/vhost.js'][33] = 0; + _$jscoverage['middleware/vhost.js'][34] = 0; + _$jscoverage['middleware/vhost.js'][35] = 0; + _$jscoverage['middleware/vhost.js'][36] = 0; + _$jscoverage['middleware/vhost.js'][37] = 0; + _$jscoverage['middleware/vhost.js'][38] = 0; +} +_$jscoverage['middleware/vhost.js'][28]++; +module.exports = (function vhost(hostname, server) { + _$jscoverage['middleware/vhost.js'][29]++; + if (! hostname) { + _$jscoverage['middleware/vhost.js'][29]++; + throw new Error("vhost hostname required"); + } + _$jscoverage['middleware/vhost.js'][30]++; + if (! server) { + _$jscoverage['middleware/vhost.js'][30]++; + throw new Error("vhost server required"); + } + _$jscoverage['middleware/vhost.js'][31]++; + var regexp = new RegExp("^" + hostname.replace(/[*]/g, "(.*?)") + "$", "i"); + _$jscoverage['middleware/vhost.js'][32]++; + if (server.onvhost) { + _$jscoverage['middleware/vhost.js'][32]++; + server.onvhost(hostname); + } + _$jscoverage['middleware/vhost.js'][33]++; + return (function vhost(req, res, next) { + _$jscoverage['middleware/vhost.js'][34]++; + if (! req.headers.host) { + _$jscoverage['middleware/vhost.js'][34]++; + return next(); + } + _$jscoverage['middleware/vhost.js'][35]++; + var host = req.headers.host.split(":")[0]; + _$jscoverage['middleware/vhost.js'][36]++; + if (! regexp.test(host)) { + _$jscoverage['middleware/vhost.js'][36]++; + return next(); + } + _$jscoverage['middleware/vhost.js'][37]++; + if ("function" == typeof server) { + _$jscoverage['middleware/vhost.js'][37]++; + return server(req, res, next); + } + _$jscoverage['middleware/vhost.js'][38]++; + server.emit("request", req, res); +}); +}); +_$jscoverage['middleware/vhost.js'].source = ["","/*!"," * Connect - vhost"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Vhost:"," * "," * Setup vhost for the given `hostname` and `server`."," *"," * connect()"," * .use(connect.vhost('foo.com', fooApp))"," * .use(connect.vhost('bar.com', barApp))"," * .use(connect.vhost('*.com', mainApp))"," *"," * The `server` may be a Connect server or"," * a regular Node `http.Server`. "," *"," * @param {String} hostname"," * @param {Server} server"," * @return {Function}"," * @api public"," */","","module.exports = function vhost(hostname, server){"," if (!hostname) throw new Error('vhost hostname required');"," if (!server) throw new Error('vhost server required');"," var regexp = new RegExp('^' + hostname.replace(/[*]/g, '(.*?)') + '$', 'i');"," if (server.onvhost) server.onvhost(hostname);"," return function vhost(req, res, next){"," if (!req.headers.host) return next();"," var host = req.headers.host.split(':')[0];"," if (!regexp.test(host)) return next();"," if ('function' == typeof server) return server(req, res, next);"," server.emit('request', req, res);"," };","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/patch.js b/node_modules/express/node_modules/connect/lib-cov/patch.js new file mode 100644 index 0000000..7d59643 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/patch.js @@ -0,0 +1,85 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['patch.js']) { + _$jscoverage['patch.js'] = []; + _$jscoverage['patch.js'][12] = 0; + _$jscoverage['patch.js'][20] = 0; + _$jscoverage['patch.js'][30] = 0; + _$jscoverage['patch.js'][31] = 0; + _$jscoverage['patch.js'][43] = 0; + _$jscoverage['patch.js'][44] = 0; + _$jscoverage['patch.js'][48] = 0; + _$jscoverage['patch.js'][49] = 0; + _$jscoverage['patch.js'][50] = 0; + _$jscoverage['patch.js'][55] = 0; + _$jscoverage['patch.js'][56] = 0; + _$jscoverage['patch.js'][59] = 0; + _$jscoverage['patch.js'][66] = 0; + _$jscoverage['patch.js'][67] = 0; + _$jscoverage['patch.js'][68] = 0; + _$jscoverage['patch.js'][69] = 0; + _$jscoverage['patch.js'][72] = 0; + _$jscoverage['patch.js'][73] = 0; + _$jscoverage['patch.js'][74] = 0; + _$jscoverage['patch.js'][75] = 0; + _$jscoverage['patch.js'][78] = 0; +} +_$jscoverage['patch.js'][12]++; +var http = require("http"), res = http.ServerResponse.prototype, setHeader = res.setHeader, _renderHeaders = res._renderHeaders, writeHead = res.writeHead; +_$jscoverage['patch.js'][20]++; +if (! res._hasConnectPatch) { + _$jscoverage['patch.js'][30]++; + res.__defineGetter__("headerSent", (function () { + _$jscoverage['patch.js'][31]++; + return this._header; +})); + _$jscoverage['patch.js'][43]++; + res.setHeader = (function (field, val) { + _$jscoverage['patch.js'][44]++; + var key = field.toLowerCase(), prev; + _$jscoverage['patch.js'][48]++; + if (this._headers && "set-cookie" == key) { + _$jscoverage['patch.js'][49]++; + if (prev = this.getHeader(field)) { + _$jscoverage['patch.js'][50]++; + val = Array.isArray(prev)? prev.concat(val): [prev, val]; + } + } + else { + _$jscoverage['patch.js'][55]++; + if ("content-type" == key && this.charset) { + _$jscoverage['patch.js'][56]++; + val += "; charset=" + this.charset; + } + } + _$jscoverage['patch.js'][59]++; + return setHeader.call(this, field, val); +}); + _$jscoverage['patch.js'][66]++; + res._renderHeaders = (function () { + _$jscoverage['patch.js'][67]++; + if (! this._emittedHeader) { + _$jscoverage['patch.js'][67]++; + this.emit("header"); + } + _$jscoverage['patch.js'][68]++; + this._emittedHeader = true; + _$jscoverage['patch.js'][69]++; + return _renderHeaders.call(this); +}); + _$jscoverage['patch.js'][72]++; + res.writeHead = (function () { + _$jscoverage['patch.js'][73]++; + if (! this._emittedHeader) { + _$jscoverage['patch.js'][73]++; + this.emit("header"); + } + _$jscoverage['patch.js'][74]++; + this._emittedHeader = true; + _$jscoverage['patch.js'][75]++; + return writeHead.apply(this, arguments); +}); + _$jscoverage['patch.js'][78]++; + res._hasConnectPatch = true; +} +_$jscoverage['patch.js'].source = ["","/*!"," * Connect"," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var http = require('http')"," , res = http.ServerResponse.prototype"," , setHeader = res.setHeader"," , _renderHeaders = res._renderHeaders"," , writeHead = res.writeHead;","","// apply only once","","if (!res._hasConnectPatch) {",""," /**"," * Provide a public \"header sent\" flag"," * until node does."," *"," * @return {Boolean}"," * @api public"," */",""," res.__defineGetter__('headerSent', function(){"," return this._header;"," });",""," /**"," * Set header `field` to `val`, special-casing"," * the `Set-Cookie` field for multiple support."," *"," * @param {String} field"," * @param {String} val"," * @api public"," */",""," res.setHeader = function(field, val){"," var key = field.toLowerCase()"," , prev;",""," // special-case Set-Cookie"," if (this._headers && 'set-cookie' == key) {"," if (prev = this.getHeader(field)) {"," val = Array.isArray(prev)"," ? prev.concat(val)"," : [prev, val];"," }"," // charset"," } else if ('content-type' == key && this.charset) {"," val += '; charset=' + this.charset;"," }",""," return setHeader.call(this, field, val);"," };",""," /**"," * Proxy to emit \"header\" event."," */",""," res._renderHeaders = function(){"," if (!this._emittedHeader) this.emit('header');"," this._emittedHeader = true;"," return _renderHeaders.call(this);"," };",""," res.writeHead = function(){"," if (!this._emittedHeader) this.emit('header');"," this._emittedHeader = true;"," return writeHead.apply(this, arguments);"," };",""," res._hasConnectPatch = true;","}"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/proto.js b/node_modules/express/node_modules/connect/lib-cov/proto.js new file mode 100644 index 0000000..e8ecb99 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/proto.js @@ -0,0 +1,285 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['proto.js']) { + _$jscoverage['proto.js'] = []; + _$jscoverage['proto.js'][13] = 0; + _$jscoverage['proto.js'][19] = 0; + _$jscoverage['proto.js'][23] = 0; + _$jscoverage['proto.js'][62] = 0; + _$jscoverage['proto.js'][64] = 0; + _$jscoverage['proto.js'][65] = 0; + _$jscoverage['proto.js'][66] = 0; + _$jscoverage['proto.js'][70] = 0; + _$jscoverage['proto.js'][71] = 0; + _$jscoverage['proto.js'][72] = 0; + _$jscoverage['proto.js'][73] = 0; + _$jscoverage['proto.js'][74] = 0; + _$jscoverage['proto.js'][79] = 0; + _$jscoverage['proto.js'][80] = 0; + _$jscoverage['proto.js'][84] = 0; + _$jscoverage['proto.js'][85] = 0; + _$jscoverage['proto.js'][89] = 0; + _$jscoverage['proto.js'][90] = 0; + _$jscoverage['proto.js'][92] = 0; + _$jscoverage['proto.js'][102] = 0; + _$jscoverage['proto.js'][103] = 0; + _$jscoverage['proto.js'][109] = 0; + _$jscoverage['proto.js'][110] = 0; + _$jscoverage['proto.js'][112] = 0; + _$jscoverage['proto.js'][113] = 0; + _$jscoverage['proto.js'][114] = 0; + _$jscoverage['proto.js'][117] = 0; + _$jscoverage['proto.js'][118] = 0; + _$jscoverage['proto.js'][119] = 0; + _$jscoverage['proto.js'][122] = 0; + _$jscoverage['proto.js'][125] = 0; + _$jscoverage['proto.js'][127] = 0; + _$jscoverage['proto.js'][130] = 0; + _$jscoverage['proto.js'][132] = 0; + _$jscoverage['proto.js'][133] = 0; + _$jscoverage['proto.js'][136] = 0; + _$jscoverage['proto.js'][139] = 0; + _$jscoverage['proto.js'][144] = 0; + _$jscoverage['proto.js'][145] = 0; + _$jscoverage['proto.js'][146] = 0; + _$jscoverage['proto.js'][147] = 0; + _$jscoverage['proto.js'][148] = 0; + _$jscoverage['proto.js'][149] = 0; + _$jscoverage['proto.js'][151] = 0; + _$jscoverage['proto.js'][152] = 0; + _$jscoverage['proto.js'][153] = 0; + _$jscoverage['proto.js'][154] = 0; + _$jscoverage['proto.js'][155] = 0; + _$jscoverage['proto.js'][157] = 0; + _$jscoverage['proto.js'][160] = 0; + _$jscoverage['proto.js'][161] = 0; + _$jscoverage['proto.js'][162] = 0; + _$jscoverage['proto.js'][165] = 0; + _$jscoverage['proto.js'][167] = 0; + _$jscoverage['proto.js'][168] = 0; + _$jscoverage['proto.js'][172] = 0; + _$jscoverage['proto.js'][173] = 0; + _$jscoverage['proto.js'][176] = 0; + _$jscoverage['proto.js'][177] = 0; + _$jscoverage['proto.js'][178] = 0; + _$jscoverage['proto.js'][181] = 0; + _$jscoverage['proto.js'][182] = 0; + _$jscoverage['proto.js'][183] = 0; + _$jscoverage['proto.js'][184] = 0; + _$jscoverage['proto.js'][185] = 0; + _$jscoverage['proto.js'][187] = 0; + _$jscoverage['proto.js'][189] = 0; + _$jscoverage['proto.js'][190] = 0; + _$jscoverage['proto.js'][192] = 0; + _$jscoverage['proto.js'][195] = 0; + _$jscoverage['proto.js'][198] = 0; + _$jscoverage['proto.js'][227] = 0; + _$jscoverage['proto.js'][228] = 0; + _$jscoverage['proto.js'][229] = 0; +} +_$jscoverage['proto.js'][13]++; +var http = require("http"), utils = require("./utils"), debug = require("debug")("connect:dispatcher"); +_$jscoverage['proto.js'][19]++; +var app = module.exports = {}; +_$jscoverage['proto.js'][23]++; +var env = process.env.NODE_ENV || "development"; +_$jscoverage['proto.js'][62]++; +app.use = (function (route, fn) { + _$jscoverage['proto.js'][64]++; + if ("string" != typeof route) { + _$jscoverage['proto.js'][65]++; + fn = route; + _$jscoverage['proto.js'][66]++; + route = "/"; + } + _$jscoverage['proto.js'][70]++; + if ("function" == typeof fn.handle) { + _$jscoverage['proto.js'][71]++; + var server = fn; + _$jscoverage['proto.js'][72]++; + fn.route = route; + _$jscoverage['proto.js'][73]++; + fn = (function (req, res, next) { + _$jscoverage['proto.js'][74]++; + server.handle(req, res, next); +}); + } + _$jscoverage['proto.js'][79]++; + if (fn instanceof http.Server) { + _$jscoverage['proto.js'][80]++; + fn = fn.listeners("request")[0]; + } + _$jscoverage['proto.js'][84]++; + if ("/" == route[route.length - 1]) { + _$jscoverage['proto.js'][85]++; + route = route.slice(0, -1); + } + _$jscoverage['proto.js'][89]++; + debug("use %s %s", route || "/", fn.name || "anonymous"); + _$jscoverage['proto.js'][90]++; + this.stack.push({route: route, handle: fn}); + _$jscoverage['proto.js'][92]++; + return this; +}); +_$jscoverage['proto.js'][102]++; +app.handle = (function (req, res, out) { + _$jscoverage['proto.js'][103]++; + var stack = this.stack, fqdn = ~ req.url.indexOf("://"), removed = "", slashAdded = false, index = 0; + _$jscoverage['proto.js'][109]++; + function next(err) { + _$jscoverage['proto.js'][110]++; + var layer, path, status, c; + _$jscoverage['proto.js'][112]++; + if (slashAdded) { + _$jscoverage['proto.js'][113]++; + req.url = req.url.substr(1); + _$jscoverage['proto.js'][114]++; + slashAdded = false; + } + _$jscoverage['proto.js'][117]++; + req.url = removed + req.url; + _$jscoverage['proto.js'][118]++; + req.originalUrl = req.originalUrl || req.url; + _$jscoverage['proto.js'][119]++; + removed = ""; + _$jscoverage['proto.js'][122]++; + layer = stack[index++]; + _$jscoverage['proto.js'][125]++; + if (! layer || res.headerSent) { + _$jscoverage['proto.js'][127]++; + if (out) { + _$jscoverage['proto.js'][127]++; + return out(err); + } + _$jscoverage['proto.js'][130]++; + if (err) { + _$jscoverage['proto.js'][132]++; + if (res.statusCode < 400) { + _$jscoverage['proto.js'][132]++; + res.statusCode = 500; + } + _$jscoverage['proto.js'][133]++; + debug("default %s", res.statusCode); + _$jscoverage['proto.js'][136]++; + if (err.status) { + _$jscoverage['proto.js'][136]++; + res.statusCode = err.status; + } + _$jscoverage['proto.js'][139]++; + var msg = "production" == env? http.STATUS_CODES[res.statusCode]: err.stack || err.toString(); + _$jscoverage['proto.js'][144]++; + if ("test" != env) { + _$jscoverage['proto.js'][144]++; + console.error(err.stack || err.toString()); + } + _$jscoverage['proto.js'][145]++; + if (res.headerSent) { + _$jscoverage['proto.js'][145]++; + return req.socket.destroy(); + } + _$jscoverage['proto.js'][146]++; + res.setHeader("Content-Type", "text/plain"); + _$jscoverage['proto.js'][147]++; + res.setHeader("Content-Length", Buffer.byteLength(msg)); + _$jscoverage['proto.js'][148]++; + if ("HEAD" == req.method) { + _$jscoverage['proto.js'][148]++; + return res.end(); + } + _$jscoverage['proto.js'][149]++; + res.end(msg); + } + else { + _$jscoverage['proto.js'][151]++; + debug("default 404"); + _$jscoverage['proto.js'][152]++; + res.statusCode = 404; + _$jscoverage['proto.js'][153]++; + res.setHeader("Content-Type", "text/plain"); + _$jscoverage['proto.js'][154]++; + if ("HEAD" == req.method) { + _$jscoverage['proto.js'][154]++; + return res.end(); + } + _$jscoverage['proto.js'][155]++; + res.end("Cannot " + req.method + " " + utils.escape(req.originalUrl)); + } + _$jscoverage['proto.js'][157]++; + return; + } + _$jscoverage['proto.js'][160]++; + try { + _$jscoverage['proto.js'][161]++; + path = utils.parseUrl(req).pathname; + _$jscoverage['proto.js'][162]++; + if (undefined == path) { + _$jscoverage['proto.js'][162]++; + path = "/"; + } + _$jscoverage['proto.js'][165]++; + if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) { + _$jscoverage['proto.js'][165]++; + return next(err); + } + _$jscoverage['proto.js'][167]++; + c = path[layer.route.length]; + _$jscoverage['proto.js'][168]++; + if (c && "/" != c && "." != c) { + _$jscoverage['proto.js'][168]++; + return next(err); + } + _$jscoverage['proto.js'][172]++; + removed = layer.route; + _$jscoverage['proto.js'][173]++; + req.url = req.url.substr(removed.length); + _$jscoverage['proto.js'][176]++; + if (! fqdn && "/" != req.url[0]) { + _$jscoverage['proto.js'][177]++; + req.url = "/" + req.url; + _$jscoverage['proto.js'][178]++; + slashAdded = true; + } + _$jscoverage['proto.js'][181]++; + debug("%s", layer.handle.name || "anonymous"); + _$jscoverage['proto.js'][182]++; + var arity = layer.handle.length; + _$jscoverage['proto.js'][183]++; + if (err) { + _$jscoverage['proto.js'][184]++; + if (arity === 4) { + _$jscoverage['proto.js'][185]++; + layer.handle(err, req, res, next); + } + else { + _$jscoverage['proto.js'][187]++; + next(err); + } + } + else { + _$jscoverage['proto.js'][189]++; + if (arity < 4) { + _$jscoverage['proto.js'][190]++; + layer.handle(req, res, next); + } + else { + _$jscoverage['proto.js'][192]++; + next(); + } + } + } + catch (e) { + _$jscoverage['proto.js'][195]++; + next(e); + } +} + _$jscoverage['proto.js'][198]++; + next(); +}); +_$jscoverage['proto.js'][227]++; +app.listen = (function () { + _$jscoverage['proto.js'][228]++; + var server = http.createServer(this); + _$jscoverage['proto.js'][229]++; + return server.listen.apply(server, arguments); +}); +_$jscoverage['proto.js'].source = ["","/*!"," * Connect - HTTPServer"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var http = require('http')"," , utils = require('./utils')"," , debug = require('debug')('connect:dispatcher');","","// prototype","","var app = module.exports = {};","","// environment","","var env = process.env.NODE_ENV || 'development';","","/**"," * Utilize the given middleware `handle` to the given `route`,"," * defaulting to _/_. This \"route\" is the mount-point for the"," * middleware, when given a value other than _/_ the middleware"," * is only effective when that segment is present in the request's"," * pathname."," *"," * For example if we were to mount a function at _/admin_, it would"," * be invoked on _/admin_, and _/admin/settings_, however it would"," * not be invoked for _/_, or _/posts_."," *"," * Examples:"," *"," * var app = connect();"," * app.use(connect.favicon());"," * app.use(connect.logger());"," * app.use(connect.static(__dirname + '/public'));"," *"," * If we wanted to prefix static files with _/public_, we could"," * \"mount\" the `static()` middleware:"," *"," * app.use('/public', connect.static(__dirname + '/public'));"," *"," * This api is chainable, so the following is valid:"," *"," * connect()"," * .use(connect.favicon())"," * .use(connect.logger())"," * .use(connect.static(__dirname + '/public'))"," * .listen(3000);"," *"," * @param {String|Function|Server} route, callback or server"," * @param {Function|Server} callback or server"," * @return {Server} for chaining"," * @api public"," */","","app.use = function(route, fn){"," // default route to '/'"," if ('string' != typeof route) {"," fn = route;"," route = '/';"," }",""," // wrap sub-apps"," if ('function' == typeof fn.handle) {"," var server = fn;"," fn.route = route;"," fn = function(req, res, next){"," server.handle(req, res, next);"," };"," }",""," // wrap vanilla http.Servers"," if (fn instanceof http.Server) {"," fn = fn.listeners('request')[0];"," }",""," // strip trailing slash"," if ('/' == route[route.length - 1]) {"," route = route.slice(0, -1);"," }",""," // add the middleware"," debug('use %s %s', route || '/', fn.name || 'anonymous');"," this.stack.push({ route: route, handle: fn });",""," return this;","};","","/**"," * Handle server requests, punting them down"," * the middleware stack."," *"," * @api private"," */","","app.handle = function(req, res, out) {"," var stack = this.stack"," , fqdn = ~req.url.indexOf('://')"," , removed = ''"," , slashAdded = false"," , index = 0;",""," function next(err) {"," var layer, path, status, c;",""," if (slashAdded) {"," req.url = req.url.substr(1);"," slashAdded = false;"," }",""," req.url = removed + req.url;"," req.originalUrl = req.originalUrl || req.url;"," removed = '';",""," // next callback"," layer = stack[index++];",""," // all done"," if (!layer || res.headerSent) {"," // delegate to parent"," if (out) return out(err);",""," // unhandled error"," if (err) {"," // default to 500"," if (res.statusCode < 400) res.statusCode = 500;"," debug('default %s', res.statusCode);",""," // respect err.status"," if (err.status) res.statusCode = err.status;",""," // production gets a basic error message"," var msg = 'production' == env"," ? http.STATUS_CODES[res.statusCode]"," : err.stack || err.toString();",""," // log to stderr in a non-test env"," if ('test' != env) console.error(err.stack || err.toString());"," if (res.headerSent) return req.socket.destroy();"," res.setHeader('Content-Type', 'text/plain');"," res.setHeader('Content-Length', Buffer.byteLength(msg));"," if ('HEAD' == req.method) return res.end();"," res.end(msg);"," } else {"," debug('default 404');"," res.statusCode = 404;"," res.setHeader('Content-Type', 'text/plain');"," if ('HEAD' == req.method) return res.end();"," res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl));"," }"," return;"," }",""," try {"," path = utils.parseUrl(req).pathname;"," if (undefined == path) path = '/';",""," // skip this layer if the route doesn't match."," if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err);",""," c = path[layer.route.length];"," if (c && '/' != c && '.' != c) return next(err);",""," // Call the layer handler"," // Trim off the part of the url that matches the route"," removed = layer.route;"," req.url = req.url.substr(removed.length);",""," // Ensure leading slash"," if (!fqdn && '/' != req.url[0]) {"," req.url = '/' + req.url;"," slashAdded = true;"," }",""," debug('%s', layer.handle.name || 'anonymous');"," var arity = layer.handle.length;"," if (err) {"," if (arity === 4) {"," layer.handle(err, req, res, next);"," } else {"," next(err);"," }"," } else if (arity < 4) {"," layer.handle(req, res, next);"," } else {"," next();"," }"," } catch (e) {"," next(e);"," }"," }"," next();","};","","/**"," * Listen for connections."," *"," * This method takes the same arguments"," * as node's `http.Server#listen()`. "," *"," * HTTP and HTTPS:"," *"," * If you run your application both as HTTP"," * and HTTPS you may wrap them individually,"," * since your Connect \"server\" is really just"," * a JavaScript `Function`."," *"," * var connect = require('connect')"," * , http = require('http')"," * , https = require('https');"," * "," * var app = connect();"," * "," * http.createServer(app).listen(80);"," * https.createServer(options, app).listen(443);"," *"," * @return {http.Server}"," * @api public"," */","","app.listen = function(){"," var server = http.createServer(this);"," return server.listen.apply(server, arguments);","};"]; diff --git a/node_modules/express/node_modules/connect/lib-cov/public/directory.html b/node_modules/express/node_modules/connect/lib-cov/public/directory.html new file mode 100644 index 0000000..15164bb --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/public/directory.html @@ -0,0 +1,75 @@ + + + listing directory {directory} + + + + + +
    +

    {linked-path}

    + {files} +
    + + \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib-cov/public/error.html b/node_modules/express/node_modules/connect/lib-cov/public/error.html new file mode 100644 index 0000000..c5ae73a --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/public/error.html @@ -0,0 +1,13 @@ + + + {error} + + + +
    +

    {title}

    +

    {statusCode} {error}

    +
      {stack}
    +
    + + diff --git a/node_modules/express/node_modules/connect/lib-cov/public/favicon.ico b/node_modules/express/node_modules/connect/lib-cov/public/favicon.ico new file mode 100644 index 0000000..895fc96 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/favicon.ico differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page.png new file mode 100644 index 0000000..03ddd79 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_add.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_add.png new file mode 100644 index 0000000..d5bfa07 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_add.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_attach.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_attach.png new file mode 100644 index 0000000..89ee2da Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_attach.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_code.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_code.png new file mode 100644 index 0000000..f7ea904 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_code.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_copy.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_copy.png new file mode 100644 index 0000000..195dc6d Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_copy.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_delete.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_delete.png new file mode 100644 index 0000000..3141467 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_delete.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_edit.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_edit.png new file mode 100644 index 0000000..046811e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_edit.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_error.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_error.png new file mode 100644 index 0000000..f07f449 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_error.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_excel.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_excel.png new file mode 100644 index 0000000..eb6158e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_excel.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_find.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_find.png new file mode 100644 index 0000000..2f19388 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_find.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_gear.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_gear.png new file mode 100644 index 0000000..8e83281 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_gear.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_go.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_go.png new file mode 100644 index 0000000..80fe1ed Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_go.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_green.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_green.png new file mode 100644 index 0000000..de8e003 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_green.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_key.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_key.png new file mode 100644 index 0000000..d6626cb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_key.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_lightning.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_lightning.png new file mode 100644 index 0000000..7e56870 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_lightning.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_link.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_link.png new file mode 100644 index 0000000..312eab0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_link.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_paintbrush.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_paintbrush.png new file mode 100644 index 0000000..246a2f0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_paintbrush.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_paste.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_paste.png new file mode 100644 index 0000000..968f073 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_paste.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_red.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_red.png new file mode 100644 index 0000000..0b18247 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_red.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_refresh.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_refresh.png new file mode 100644 index 0000000..cf347c7 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_refresh.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_save.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_save.png new file mode 100644 index 0000000..caea546 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_save.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white.png new file mode 100644 index 0000000..8b8b1ca Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_acrobat.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_acrobat.png new file mode 100644 index 0000000..8f8095e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_acrobat.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_actionscript.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_actionscript.png new file mode 100644 index 0000000..159b240 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_actionscript.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_add.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_add.png new file mode 100644 index 0000000..aa23dde Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_add.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_c.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_c.png new file mode 100644 index 0000000..34a05cc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_c.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_camera.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_camera.png new file mode 100644 index 0000000..f501a59 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_camera.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cd.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cd.png new file mode 100644 index 0000000..848bdaf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cd.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_code.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_code.png new file mode 100644 index 0000000..0c76bd1 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_code.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_code_red.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_code_red.png new file mode 100644 index 0000000..87a6914 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_code_red.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_coldfusion.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000..c66011f Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_coldfusion.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_compressed.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_compressed.png new file mode 100644 index 0000000..2b6b100 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_compressed.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_copy.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_copy.png new file mode 100644 index 0000000..a9f31a2 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_copy.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cplusplus.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cplusplus.png new file mode 100644 index 0000000..a87cf84 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cplusplus.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_csharp.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_csharp.png new file mode 100644 index 0000000..ffb8fc9 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_csharp.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cup.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cup.png new file mode 100644 index 0000000..0a7d6f4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_cup.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_database.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_database.png new file mode 100644 index 0000000..bddba1f Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_database.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_delete.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_delete.png new file mode 100644 index 0000000..af1ecaf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_delete.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_dvd.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_dvd.png new file mode 100644 index 0000000..4cc537a Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_dvd.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_edit.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_edit.png new file mode 100644 index 0000000..b93e776 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_edit.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_error.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_error.png new file mode 100644 index 0000000..9fc5a0a Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_error.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_excel.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_excel.png new file mode 100644 index 0000000..b977d7e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_excel.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_find.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_find.png new file mode 100644 index 0000000..5818436 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_find.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_flash.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_flash.png new file mode 100644 index 0000000..5769120 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_flash.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_freehand.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_freehand.png new file mode 100644 index 0000000..8d719df Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_freehand.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_gear.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_gear.png new file mode 100644 index 0000000..106f5aa Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_gear.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_get.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_get.png new file mode 100644 index 0000000..e4a1ecb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_get.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_go.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_go.png new file mode 100644 index 0000000..7e62a92 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_go.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_h.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_h.png new file mode 100644 index 0000000..e902abb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_h.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_horizontal.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_horizontal.png new file mode 100644 index 0000000..1d2d0a4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_horizontal.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_key.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_key.png new file mode 100644 index 0000000..d616484 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_key.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_lightning.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_lightning.png new file mode 100644 index 0000000..7215d1e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_lightning.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_link.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_link.png new file mode 100644 index 0000000..bf7bd1c Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_link.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_magnify.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_magnify.png new file mode 100644 index 0000000..f6b74cc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_magnify.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_medal.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_medal.png new file mode 100644 index 0000000..d3fffb6 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_medal.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_office.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_office.png new file mode 100644 index 0000000..a65bcb3 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_office.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paint.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paint.png new file mode 100644 index 0000000..23a37b8 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paint.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paintbrush.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paintbrush.png new file mode 100644 index 0000000..f907e44 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paintbrush.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paste.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paste.png new file mode 100644 index 0000000..5b2cbb3 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_paste.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_php.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_php.png new file mode 100644 index 0000000..7868a25 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_php.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_picture.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_picture.png new file mode 100644 index 0000000..134b669 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_picture.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_powerpoint.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000..c4eff03 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_powerpoint.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_put.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_put.png new file mode 100644 index 0000000..884ffd6 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_put.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_ruby.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_ruby.png new file mode 100644 index 0000000..f59b7c4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_ruby.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_stack.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_stack.png new file mode 100644 index 0000000..44084ad Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_stack.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_star.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_star.png new file mode 100644 index 0000000..3a1441c Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_star.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_swoosh.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_swoosh.png new file mode 100644 index 0000000..e770829 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_swoosh.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_text.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_text.png new file mode 100644 index 0000000..813f712 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_text.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_text_width.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_text_width.png new file mode 100644 index 0000000..d9cf132 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_text_width.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_tux.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_tux.png new file mode 100644 index 0000000..52699bf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_tux.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_vector.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_vector.png new file mode 100644 index 0000000..4a05955 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_vector.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_visualstudio.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_visualstudio.png new file mode 100644 index 0000000..a0a433d Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_visualstudio.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_width.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_width.png new file mode 100644 index 0000000..1eb8809 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_width.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_word.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_word.png new file mode 100644 index 0000000..ae8ecbf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_word.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_world.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_world.png new file mode 100644 index 0000000..6ed2490 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_world.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_wrench.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_wrench.png new file mode 100644 index 0000000..fecadd0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_wrench.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_zip.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_zip.png new file mode 100644 index 0000000..fd4bbcc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_white_zip.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_word.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_word.png new file mode 100644 index 0000000..834cdfa Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_word.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/icons/page_world.png b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_world.png new file mode 100644 index 0000000..b8895dd Binary files /dev/null and b/node_modules/express/node_modules/connect/lib-cov/public/icons/page_world.png differ diff --git a/node_modules/express/node_modules/connect/lib-cov/public/style.css b/node_modules/express/node_modules/connect/lib-cov/public/style.css new file mode 100644 index 0000000..32b6507 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/public/style.css @@ -0,0 +1,141 @@ +body { + margin: 0; + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + margin: 0; + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul { + margin: 0; + padding: 0; +} +ul li { + margin: 5px 0; + padding: 3px 8px; + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 500px; +} +ul#files li { + padding: 0; +} +ul#files li img { + position: absolute; + top: 5px; + left: 5px; +} +ul#files li a { + position: relative; + display: block; + margin: 1px; + width: 30%; + height: 25px; + line-height: 25px; + text-indent: 8px; + float: left; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + text-overflow: ellipsis; +} +ul#files li a.icon { + text-indent: 25px; +} +ul#files li a:focus, +ul#files li a:hover { + outline: none; + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} diff --git a/node_modules/express/node_modules/connect/lib-cov/utils.js b/node_modules/express/node_modules/connect/lib-cov/utils.js new file mode 100644 index 0000000..2200dce --- /dev/null +++ b/node_modules/express/node_modules/connect/lib-cov/utils.js @@ -0,0 +1,282 @@ +/* automatically generated by JSCoverage - do not edit */ +if (typeof _$jscoverage === 'undefined') _$jscoverage = {}; +if (! _$jscoverage['utils.js']) { + _$jscoverage['utils.js'] = []; + _$jscoverage['utils.js'][13] = 0; + _$jscoverage['utils.js'][26] = 0; + _$jscoverage['utils.js'][27] = 0; + _$jscoverage['utils.js'][39] = 0; + _$jscoverage['utils.js'][40] = 0; + _$jscoverage['utils.js'][41] = 0; + _$jscoverage['utils.js'][54] = 0; + _$jscoverage['utils.js'][55] = 0; + _$jscoverage['utils.js'][56] = 0; + _$jscoverage['utils.js'][57] = 0; + _$jscoverage['utils.js'][73] = 0; + _$jscoverage['utils.js'][74] = 0; + _$jscoverage['utils.js'][95] = 0; + _$jscoverage['utils.js'][96] = 0; + _$jscoverage['utils.js'][97] = 0; + _$jscoverage['utils.js'][98] = 0; + _$jscoverage['utils.js'][101] = 0; + _$jscoverage['utils.js'][112] = 0; + _$jscoverage['utils.js'][113] = 0; + _$jscoverage['utils.js'][132] = 0; + _$jscoverage['utils.js'][133] = 0; + _$jscoverage['utils.js'][147] = 0; + _$jscoverage['utils.js'][148] = 0; + _$jscoverage['utils.js'][149] = 0; + _$jscoverage['utils.js'][166] = 0; + _$jscoverage['utils.js'][167] = 0; + _$jscoverage['utils.js'][168] = 0; + _$jscoverage['utils.js'][169] = 0; + _$jscoverage['utils.js'][184] = 0; + _$jscoverage['utils.js'][185] = 0; + _$jscoverage['utils.js'][186] = 0; + _$jscoverage['utils.js'][187] = 0; + _$jscoverage['utils.js'][188] = 0; + _$jscoverage['utils.js'][189] = 0; + _$jscoverage['utils.js'][190] = 0; + _$jscoverage['utils.js'][191] = 0; + _$jscoverage['utils.js'][192] = 0; + _$jscoverage['utils.js'][196] = 0; + _$jscoverage['utils.js'][208] = 0; + _$jscoverage['utils.js'][209] = 0; + _$jscoverage['utils.js'][222] = 0; + _$jscoverage['utils.js'][223] = 0; + _$jscoverage['utils.js'][224] = 0; + _$jscoverage['utils.js'][225] = 0; + _$jscoverage['utils.js'][226] = 0; + _$jscoverage['utils.js'][228] = 0; + _$jscoverage['utils.js'][239] = 0; + _$jscoverage['utils.js'][240] = 0; + _$jscoverage['utils.js'][241] = 0; + _$jscoverage['utils.js'][242] = 0; + _$jscoverage['utils.js'][267] = 0; + _$jscoverage['utils.js'][276] = 0; + _$jscoverage['utils.js'][277] = 0; + _$jscoverage['utils.js'][278] = 0; + _$jscoverage['utils.js'][279] = 0; + _$jscoverage['utils.js'][292] = 0; + _$jscoverage['utils.js'][293] = 0; + _$jscoverage['utils.js'][305] = 0; + _$jscoverage['utils.js'][306] = 0; + _$jscoverage['utils.js'][307] = 0; + _$jscoverage['utils.js'][308] = 0; + _$jscoverage['utils.js'][319] = 0; + _$jscoverage['utils.js'][320] = 0; + _$jscoverage['utils.js'][321] = 0; + _$jscoverage['utils.js'][322] = 0; + _$jscoverage['utils.js'][334] = 0; + _$jscoverage['utils.js'][335] = 0; + _$jscoverage['utils.js'][346] = 0; + _$jscoverage['utils.js'][347] = 0; + _$jscoverage['utils.js'][350] = 0; + _$jscoverage['utils.js'][351] = 0; + _$jscoverage['utils.js'][355] = 0; + _$jscoverage['utils.js'][358] = 0; + _$jscoverage['utils.js'][369] = 0; + _$jscoverage['utils.js'][370] = 0; + _$jscoverage['utils.js'][371] = 0; + _$jscoverage['utils.js'][372] = 0; + _$jscoverage['utils.js'][374] = 0; + _$jscoverage['utils.js'][386] = 0; +} +_$jscoverage['utils.js'][13]++; +var http = require("http"), crypto = require("crypto"), parse = require("url").parse, signature = require("cookie-signature"); +_$jscoverage['utils.js'][26]++; +exports.hasBody = (function (req) { + _$jscoverage['utils.js'][27]++; + return "transfer-encoding" in req.headers || "content-length" in req.headers; +}); +_$jscoverage['utils.js'][39]++; +exports.mime = (function (req) { + _$jscoverage['utils.js'][40]++; + var str = req.headers["content-type"] || ""; + _$jscoverage['utils.js'][41]++; + return str.split(";")[0]; +}); +_$jscoverage['utils.js'][54]++; +exports.error = (function (code, msg) { + _$jscoverage['utils.js'][55]++; + var err = new Error(msg || http.STATUS_CODES[code]); + _$jscoverage['utils.js'][56]++; + err.status = code; + _$jscoverage['utils.js'][57]++; + return err; +}); +_$jscoverage['utils.js'][73]++; +exports.md5 = (function (str, encoding) { + _$jscoverage['utils.js'][74]++; + return crypto.createHash("md5").update(str).digest(encoding || "hex"); +}); +_$jscoverage['utils.js'][95]++; +exports.merge = (function (a, b) { + _$jscoverage['utils.js'][96]++; + if (a && b) { + _$jscoverage['utils.js'][97]++; + for (var key in b) { + _$jscoverage['utils.js'][98]++; + a[key] = b[key]; +} + } + _$jscoverage['utils.js'][101]++; + return a; +}); +_$jscoverage['utils.js'][112]++; +exports.escape = (function (html) { + _$jscoverage['utils.js'][113]++; + return String(html).replace(/&(?!\w+;)/g, "&").replace(//g, ">").replace(/"/g, """); +}); +_$jscoverage['utils.js'][132]++; +exports.uid = (function (len) { + _$jscoverage['utils.js'][133]++; + return crypto.randomBytes(Math.ceil(len * 3 / 4)).toString("base64").slice(0, len); +}); +_$jscoverage['utils.js'][147]++; +exports.sign = (function (val, secret) { + _$jscoverage['utils.js'][148]++; + console.warn("do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature"); + _$jscoverage['utils.js'][149]++; + return val + "." + crypto.createHmac("sha256", secret).update(val).digest("base64").replace(/=+$/, ""); +}); +_$jscoverage['utils.js'][166]++; +exports.unsign = (function (val, secret) { + _$jscoverage['utils.js'][167]++; + console.warn("do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature"); + _$jscoverage['utils.js'][168]++; + var str = val.slice(0, val.lastIndexOf(".")); + _$jscoverage['utils.js'][169]++; + return exports.sign(str, secret) == val? str: false; +}); +_$jscoverage['utils.js'][184]++; +exports.parseSignedCookies = (function (obj, secret) { + _$jscoverage['utils.js'][185]++; + var ret = {}; + _$jscoverage['utils.js'][186]++; + Object.keys(obj).forEach((function (key) { + _$jscoverage['utils.js'][187]++; + var val = obj[key]; + _$jscoverage['utils.js'][188]++; + if (0 == val.indexOf("s:")) { + _$jscoverage['utils.js'][189]++; + val = signature.unsign(val.slice(2), secret); + _$jscoverage['utils.js'][190]++; + if (val) { + _$jscoverage['utils.js'][191]++; + ret[key] = val; + _$jscoverage['utils.js'][192]++; + delete obj[key]; + } + } +})); + _$jscoverage['utils.js'][196]++; + return ret; +}); +_$jscoverage['utils.js'][208]++; +exports.parseSignedCookie = (function (str, secret) { + _$jscoverage['utils.js'][209]++; + return 0 == str.indexOf("s:")? signature.unsign(str.slice(2), secret): str; +}); +_$jscoverage['utils.js'][222]++; +exports.parseJSONCookies = (function (obj) { + _$jscoverage['utils.js'][223]++; + Object.keys(obj).forEach((function (key) { + _$jscoverage['utils.js'][224]++; + var val = obj[key]; + _$jscoverage['utils.js'][225]++; + var res = exports.parseJSONCookie(val); + _$jscoverage['utils.js'][226]++; + if (res) { + _$jscoverage['utils.js'][226]++; + obj[key] = res; + } +})); + _$jscoverage['utils.js'][228]++; + return obj; +}); +_$jscoverage['utils.js'][239]++; +exports.parseJSONCookie = (function (str) { + _$jscoverage['utils.js'][240]++; + if (0 == str.indexOf("j:")) { + _$jscoverage['utils.js'][241]++; + try { + _$jscoverage['utils.js'][242]++; + return JSON.parse(str.slice(2)); + } + catch (err) { + } + } +}); +_$jscoverage['utils.js'][267]++; +exports.pause = require("pause"); +_$jscoverage['utils.js'][276]++; +exports.removeContentHeaders = (function (res) { + _$jscoverage['utils.js'][277]++; + Object.keys(res._headers).forEach((function (field) { + _$jscoverage['utils.js'][278]++; + if (0 == field.indexOf("content")) { + _$jscoverage['utils.js'][279]++; + res.removeHeader(field); + } +})); +}); +_$jscoverage['utils.js'][292]++; +exports.conditionalGET = (function (req) { + _$jscoverage['utils.js'][293]++; + return req.headers["if-modified-since"] || req.headers["if-none-match"]; +}); +_$jscoverage['utils.js'][305]++; +exports.unauthorized = (function (res, realm) { + _$jscoverage['utils.js'][306]++; + res.statusCode = 401; + _$jscoverage['utils.js'][307]++; + res.setHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\""); + _$jscoverage['utils.js'][308]++; + res.end("Unauthorized"); +}); +_$jscoverage['utils.js'][319]++; +exports.notModified = (function (res) { + _$jscoverage['utils.js'][320]++; + exports.removeContentHeaders(res); + _$jscoverage['utils.js'][321]++; + res.statusCode = 304; + _$jscoverage['utils.js'][322]++; + res.end(); +}); +_$jscoverage['utils.js'][334]++; +exports.etag = (function (stat) { + _$jscoverage['utils.js'][335]++; + return "\"" + stat.size + "-" + Number(stat.mtime) + "\""; +}); +_$jscoverage['utils.js'][346]++; +exports.parseCacheControl = (function (str) { + _$jscoverage['utils.js'][347]++; + var directives = str.split(","), obj = {}; + _$jscoverage['utils.js'][350]++; + for (var i = 0, len = directives.length; i < len; i++) { + _$jscoverage['utils.js'][351]++; + var parts = directives[i].split("="), key = parts.shift().trim(), val = parseInt(parts.shift(), 10); + _$jscoverage['utils.js'][355]++; + obj[key] = isNaN(val)? true: val; +} + _$jscoverage['utils.js'][358]++; + return obj; +}); +_$jscoverage['utils.js'][369]++; +exports.parseUrl = (function (req) { + _$jscoverage['utils.js'][370]++; + var parsed = req._parsedUrl; + _$jscoverage['utils.js'][371]++; + if (parsed && parsed.href == req.url) { + _$jscoverage['utils.js'][372]++; + return parsed; + } + else { + _$jscoverage['utils.js'][374]++; + return req._parsedUrl = parse(req.url); + } +}); +_$jscoverage['utils.js'][386]++; +exports.parseBytes = require("bytes"); +_$jscoverage['utils.js'].source = ["","/*!"," * Connect - utils"," * Copyright(c) 2010 Sencha Inc."," * Copyright(c) 2011 TJ Holowaychuk"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var http = require('http')"," , crypto = require('crypto')"," , parse = require('url').parse"," , signature = require('cookie-signature');","","/**"," * Return `true` if the request has a body, otherwise return `false`."," *"," * @param {IncomingMessage} req"," * @return {Boolean}"," * @api private"," */","","exports.hasBody = function(req) {"," return 'transfer-encoding' in req.headers || 'content-length' in req.headers;","};","","/**"," * Extract the mime type from the given request's"," * _Content-Type_ header."," *"," * @param {IncomingMessage} req"," * @return {String}"," * @api private"," */","","exports.mime = function(req) {"," var str = req.headers['content-type'] || '';"," return str.split(';')[0];","};","","/**"," * Generate an `Error` from the given status `code`"," * and optional `msg`."," *"," * @param {Number} code"," * @param {String} msg"," * @return {Error}"," * @api private"," */","","exports.error = function(code, msg){"," var err = new Error(msg || http.STATUS_CODES[code]);"," err.status = code;"," return err;","};","","/**"," * Return md5 hash of the given string and optional encoding,"," * defaulting to hex."," *"," * utils.md5('wahoo');"," * // => \"e493298061761236c96b02ea6aa8a2ad\""," *"," * @param {String} str"," * @param {String} encoding"," * @return {String}"," * @api private"," */","","exports.md5 = function(str, encoding){"," return crypto"," .createHash('md5')"," .update(str)"," .digest(encoding || 'hex');","};","","/**"," * Merge object b with object a."," *"," * var a = { foo: 'bar' }"," * , b = { bar: 'baz' };"," * "," * utils.merge(a, b);"," * // => { foo: 'bar', bar: 'baz' }"," *"," * @param {Object} a"," * @param {Object} b"," * @return {Object}"," * @api private"," */","","exports.merge = function(a, b){"," if (a && b) {"," for (var key in b) {"," a[key] = b[key];"," }"," }"," return a;","};","","/**"," * Escape the given string of `html`."," *"," * @param {String} html"," * @return {String}"," * @api private"," */","","exports.escape = function(html){"," return String(html)"," .replace(/&(?!\\w+;)/g, '&amp;')"," .replace(/</g, '&lt;')"," .replace(/>/g, '&gt;')"," .replace(/\"/g, '&quot;');","};","","","/**"," * Return a unique identifier with the given `len`."," *"," * utils.uid(10);"," * // => \"FDaS435D2z\""," *"," * @param {Number} len"," * @return {String}"," * @api private"," */","","exports.uid = function(len) {"," return crypto.randomBytes(Math.ceil(len * 3 / 4))"," .toString('base64')"," .slice(0, len);","};","","/**"," * Sign the given `val` with `secret`."," *"," * @param {String} val"," * @param {String} secret"," * @return {String}"," * @api private"," */","","exports.sign = function(val, secret){"," console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature')"," return val + '.' + crypto"," .createHmac('sha256', secret)"," .update(val)"," .digest('base64')"," .replace(/=+$/, '');","};","","/**"," * Unsign and decode the given `val` with `secret`,"," * returning `false` if the signature is invalid."," *"," * @param {String} val"," * @param {String} secret"," * @return {String|Boolean}"," * @api private"," */","","exports.unsign = function(val, secret){"," console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature')"," var str = val.slice(0, val.lastIndexOf('.'));"," return exports.sign(str, secret) == val"," ? str"," : false;","};","","/**"," * Parse signed cookies, returning an object"," * containing the decoded key/value pairs,"," * while removing the signed key from `obj`."," *"," * @param {Object} obj"," * @return {Object}"," * @api private"," */","","exports.parseSignedCookies = function(obj, secret){"," var ret = {};"," Object.keys(obj).forEach(function(key){"," var val = obj[key];"," if (0 == val.indexOf('s:')) {"," val = signature.unsign(val.slice(2), secret);"," if (val) {"," ret[key] = val;"," delete obj[key];"," }"," }"," });"," return ret;","};","","/**"," * Parse a signed cookie string, return the decoded value"," *"," * @param {String} str signed cookie string"," * @param {String} secret"," * @return {String} decoded value"," * @api private"," */","","exports.parseSignedCookie = function(str, secret){"," return 0 == str.indexOf('s:')"," ? signature.unsign(str.slice(2), secret)"," : str;","};","","/**"," * Parse JSON cookies."," *"," * @param {Object} obj"," * @return {Object}"," * @api private"," */","","exports.parseJSONCookies = function(obj){"," Object.keys(obj).forEach(function(key){"," var val = obj[key];"," var res = exports.parseJSONCookie(val);"," if (res) obj[key] = res;"," });"," return obj;","};","","/**"," * Parse JSON cookie string"," *"," * @param {String} str"," * @return {Object} Parsed object or null if not json cookie"," * @api private"," */","","exports.parseJSONCookie = function(str) {"," if (0 == str.indexOf('j:')) {"," try {"," return JSON.parse(str.slice(2));"," } catch (err) {"," // no op"," }"," }","};","","/**"," * Pause `data` and `end` events on the given `obj`."," * Middleware performing async tasks _should_ utilize"," * this utility (or similar), to re-emit data once"," * the async operation has completed, otherwise these"," * events may be lost."," *"," * var pause = utils.pause(req);"," * fs.readFile(path, function(){"," * next();"," * pause.resume();"," * });"," *"," * @param {Object} obj"," * @return {Object}"," * @api private"," */","","exports.pause = require('pause');","","/**"," * Strip `Content-*` headers from `res`."," *"," * @param {ServerResponse} res"," * @api private"," */","","exports.removeContentHeaders = function(res){"," Object.keys(res._headers).forEach(function(field){"," if (0 == field.indexOf('content')) {"," res.removeHeader(field);"," }"," });","};","","/**"," * Check if `req` is a conditional GET request."," *"," * @param {IncomingMessage} req"," * @return {Boolean}"," * @api private"," */","","exports.conditionalGET = function(req) {"," return req.headers['if-modified-since']"," || req.headers['if-none-match'];","};","","/**"," * Respond with 401 \"Unauthorized\"."," *"," * @param {ServerResponse} res"," * @param {String} realm"," * @api private"," */","","exports.unauthorized = function(res, realm) {"," res.statusCode = 401;"," res.setHeader('WWW-Authenticate', 'Basic realm=\"' + realm + '\"');"," res.end('Unauthorized');","};","","/**"," * Respond with 304 \"Not Modified\"."," *"," * @param {ServerResponse} res"," * @param {Object} headers"," * @api private"," */","","exports.notModified = function(res) {"," exports.removeContentHeaders(res);"," res.statusCode = 304;"," res.end();","};","","/**"," * Return an ETag in the form of `\"<size>-<mtime>\"`"," * from the given `stat`."," *"," * @param {Object} stat"," * @return {String}"," * @api private"," */","","exports.etag = function(stat) {"," return '\"' + stat.size + '-' + Number(stat.mtime) + '\"';","};","","/**"," * Parse the given Cache-Control `str`."," *"," * @param {String} str"," * @return {Object}"," * @api private"," */","","exports.parseCacheControl = function(str){"," var directives = str.split(',')"," , obj = {};",""," for(var i = 0, len = directives.length; i < len; i++) {"," var parts = directives[i].split('=')"," , key = parts.shift().trim()"," , val = parseInt(parts.shift(), 10);",""," obj[key] = isNaN(val) ? true : val;"," }",""," return obj;","};","","/**"," * Parse the `req` url with memoization."," *"," * @param {ServerRequest} req"," * @return {Object}"," * @api private"," */","","exports.parseUrl = function(req){"," var parsed = req._parsedUrl;"," if (parsed && parsed.href == req.url) {"," return parsed;"," } else {"," return req._parsedUrl = parse(req.url);"," }","};","","/**"," * Parse byte `size` string."," *"," * @param {String} size"," * @return {Number}"," * @api private"," */","","exports.parseBytes = require('bytes');"]; diff --git a/node_modules/express/node_modules/connect/lib/cache.js b/node_modules/express/node_modules/connect/lib/cache.js new file mode 100644 index 0000000..052fcdb --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/cache.js @@ -0,0 +1,81 @@ + +/*! + * Connect - Cache + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Expose `Cache`. + */ + +module.exports = Cache; + +/** + * LRU cache store. + * + * @param {Number} limit + * @api private + */ + +function Cache(limit) { + this.store = {}; + this.keys = []; + this.limit = limit; +} + +/** + * Touch `key`, promoting the object. + * + * @param {String} key + * @param {Number} i + * @api private + */ + +Cache.prototype.touch = function(key, i){ + this.keys.splice(i,1); + this.keys.push(key); +}; + +/** + * Remove `key`. + * + * @param {String} key + * @api private + */ + +Cache.prototype.remove = function(key){ + delete this.store[key]; +}; + +/** + * Get the object stored for `key`. + * + * @param {String} key + * @return {Array} + * @api private + */ + +Cache.prototype.get = function(key){ + return this.store[key]; +}; + +/** + * Add a cache `key`. + * + * @param {String} key + * @return {Array} + * @api private + */ + +Cache.prototype.add = function(key){ + // initialize store + var len = this.keys.push(key); + + // limit reached, invalidate LRU + if (len > this.limit) this.remove(this.keys.shift()); + + var arr = this.store[key] = []; + arr.createdAt = new Date; + return arr; +}; diff --git a/node_modules/express/node_modules/connect/lib/connect.js b/node_modules/express/node_modules/connect/lib/connect.js new file mode 100644 index 0000000..a067e24 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/connect.js @@ -0,0 +1,93 @@ + +/*! + * Connect + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , proto = require('./proto') + , utils = require('./utils') + , path = require('path') + , basename = path.basename + , fs = require('fs'); + +// node patches + +require('./patch'); + +// expose createServer() as the module + +exports = module.exports = createServer; + +/** + * Framework version. + */ + +exports.version = '2.7.2'; + +/** + * Expose mime module. + */ + +exports.mime = require('./middleware/static').mime; + +/** + * Expose the prototype. + */ + +exports.proto = proto; + +/** + * Auto-load middleware getters. + */ + +exports.middleware = {}; + +/** + * Expose utilities. + */ + +exports.utils = utils; + +/** + * Create a new connect server. + * + * @return {Function} + * @api public + */ + +function createServer() { + function app(req, res){ app.handle(req, res); } + utils.merge(app, proto); + utils.merge(app, EventEmitter.prototype); + app.route = '/'; + app.stack = []; + for (var i = 0; i < arguments.length; ++i) { + app.use(arguments[i]); + } + return app; +}; + +/** + * Support old `.createServer()` method. + */ + +createServer.createServer = createServer; + +/** + * Auto-load bundled middleware with getters. + */ + +fs.readdirSync(__dirname + '/middleware').forEach(function(filename){ + if (!/\.js$/.test(filename)) return; + var name = basename(filename, '.js'); + function load(){ return require('./middleware/' + name); } + exports.middleware.__defineGetter__(name, load); + exports.__defineGetter__(name, load); +}); diff --git a/node_modules/express/node_modules/connect/lib/index.js b/node_modules/express/node_modules/connect/lib/index.js new file mode 100644 index 0000000..2618ddc --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/index.js @@ -0,0 +1,50 @@ + +/** + * Connect is a middleware framework for node, + * shipping with over 18 bundled middleware and a rich selection of + * 3rd-party middleware. + * + * var app = connect() + * .use(connect.logger('dev')) + * .use(connect.static('public')) + * .use(function(req, res){ + * res.end('hello world\n'); + * }) + * .listen(3000); + * + * Installation: + * + * $ npm install connect + * + * Middleware: + * + * - [logger](logger.html) request logger with custom format support + * - [csrf](csrf.html) Cross-site request forgery protection + * - [compress](compress.html) Gzip compression middleware + * - [basicAuth](basicAuth.html) basic http authentication + * - [bodyParser](bodyParser.html) extensible request body parser + * - [json](json.html) application/json parser + * - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser + * - [multipart](multipart.html) multipart/form-data parser + * - [timeout](timeout.html) request timeouts + * - [cookieParser](cookieParser.html) cookie parser + * - [session](session.html) session management support with bundled MemoryStore + * - [cookieSession](cookieSession.html) cookie-based session support + * - [methodOverride](methodOverride.html) faux HTTP method support + * - [responseTime](responseTime.html) calculates response-time and exposes via X-Response-Time + * - [staticCache](staticCache.html) memory cache layer for the static() middleware + * - [static](static.html) streaming static file server supporting `Range` and more + * - [directory](directory.html) directory listing middleware + * - [vhost](vhost.html) virtual host sub-domain mapping middleware + * - [favicon](favicon.html) efficient favicon server (with default icon) + * - [limit](limit.html) limit the bytesize of request bodies + * - [query](query.html) automatic querystring parser, populating `req.query` + * - [errorHandler](errorHandler.html) flexible error handler + * + * Links: + * + * - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware + * - GitHub [repository](http://github.com/senchalabs/connect) + * - [test documentation](https://github.com/senchalabs/connect/blob/gh-pages/tests.md) + * + */ \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js b/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js new file mode 100644 index 0000000..0205812 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js @@ -0,0 +1,103 @@ + +/*! + * Connect - basicAuth + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , unauthorized = utils.unauthorized; + +/** + * Basic Auth: + * + * Enfore basic authentication by providing a `callback(user, pass)`, + * which must return `true` in order to gain access. Alternatively an async + * method is provided as well, invoking `callback(user, pass, callback)`. Populates + * `req.user`. The final alternative is simply passing username / password + * strings. + * + * Simple username and password + * + * connect(connect.basicAuth('username', 'password')); + * + * Callback verification + * + * connect() + * .use(connect.basicAuth(function(user, pass){ + * return 'tj' == user & 'wahoo' == pass; + * })) + * + * Async callback verification, accepting `fn(err, user)`. + * + * connect() + * .use(connect.basicAuth(function(user, pass, fn){ + * User.authenticate({ user: user, pass: pass }, fn); + * })) + * + * @param {Function|String} callback or username + * @param {String} realm + * @api public + */ + +module.exports = function basicAuth(callback, realm) { + var username, password; + + // user / pass strings + if ('string' == typeof callback) { + username = callback; + password = realm; + if ('string' != typeof password) throw new Error('password argument required'); + realm = arguments[2]; + callback = function(user, pass){ + return user == username && pass == password; + } + } + + realm = realm || 'Authorization Required'; + + return function(req, res, next) { + var authorization = req.headers.authorization; + + if (req.user) return next(); + if (!authorization) return unauthorized(res, realm); + + var parts = authorization.split(' '); + + if (parts.length !== 2) return next(400); + + var scheme = parts[0] + , credentials = new Buffer(parts[1], 'base64').toString() + , index = credentials.indexOf(':'); + + if ('Basic' != scheme || index < 0) return next(400); + + var user = credentials.slice(0, index) + , pass = credentials.slice(index + 1); + + // async + if (callback.length >= 3) { + var pause = utils.pause(req); + callback(user, pass, function(err, user){ + if (err || !user) return unauthorized(res, realm); + req.user = req.remoteUser = user; + next(); + pause.resume(); + }); + // sync + } else { + if (callback(user, pass)) { + req.user = req.remoteUser = user; + next(); + } else { + unauthorized(res, realm); + } + } + } +}; + diff --git a/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js b/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js new file mode 100644 index 0000000..9f692cd --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js @@ -0,0 +1,61 @@ + +/*! + * Connect - bodyParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var multipart = require('./multipart') + , urlencoded = require('./urlencoded') + , json = require('./json'); + +/** + * Body parser: + * + * Parse request bodies, supports _application/json_, + * _application/x-www-form-urlencoded_, and _multipart/form-data_. + * + * This is equivalent to: + * + * app.use(connect.json()); + * app.use(connect.urlencoded()); + * app.use(connect.multipart()); + * + * Examples: + * + * connect() + * .use(connect.bodyParser()) + * .use(function(req, res) { + * res.end('viewing user ' + req.body.user.name); + * }); + * + * $ curl -d 'user[name]=tj' http://local/ + * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://local/ + * + * View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function bodyParser(options){ + var _urlencoded = urlencoded(options) + , _multipart = multipart(options) + , _json = json(options); + + return function bodyParser(req, res, next) { + _json(req, res, function(err){ + if (err) return next(err); + _urlencoded(req, res, function(err){ + if (err) return next(err); + _multipart(req, res, next); + }); + }); + } +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/middleware/compress.js b/node_modules/express/node_modules/connect/lib/middleware/compress.js new file mode 100644 index 0000000..2dc6437 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/compress.js @@ -0,0 +1,147 @@ +/*! + * Connect - compress + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var zlib = require('zlib'); + +/** + * Supported content-encoding methods. + */ + +exports.methods = { + gzip: zlib.createGzip + , deflate: zlib.createDeflate +}; + +/** + * Default filter function. + */ + +exports.filter = function(req, res){ + return /json|text|javascript/.test(res.getHeader('Content-Type')); +}; + +/** + * Compress: + * + * Compress response data with gzip/deflate. + * + * Filter: + * + * A `filter` callback function may be passed to + * replace the default logic of: + * + * exports.filter = function(req, res){ + * return /json|text|javascript/.test(res.getHeader('Content-Type')); + * }; + * + * Options: + * + * All remaining options are passed to the gzip/deflate + * creation functions. Consult node's docs for additional details. + * + * - `chunkSize` (default: 16*1024) + * - `windowBits` + * - `level`: 0-9 where 0 is no compression, and 9 is slow but best compression + * - `memLevel`: 1-9 low is slower but uses less memory, high is fast but uses more + * - `strategy`: compression strategy + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function compress(options) { + options = options || {}; + var names = Object.keys(exports.methods) + , filter = options.filter || exports.filter; + + return function(req, res, next){ + var accept = req.headers['accept-encoding'] + , write = res.write + , end = res.end + , stream + , method; + + // vary + res.setHeader('Vary', 'Accept-Encoding'); + + // proxy + + res.write = function(chunk, encoding){ + if (!this.headerSent) this._implicitHeader(); + return stream + ? stream.write(new Buffer(chunk, encoding)) + : write.call(res, chunk, encoding); + }; + + res.end = function(chunk, encoding){ + if (chunk) this.write(chunk, encoding); + return stream + ? stream.end() + : end.call(res); + }; + + res.on('header', function(){ + var encoding = res.getHeader('Content-Encoding') || 'identity'; + + // already encoded + if ('identity' != encoding) return; + + // default request filter + if (!filter(req, res)) return; + + // SHOULD use identity + if (!accept) return; + + // head + if ('HEAD' == req.method) return; + + // default to gzip + if ('*' == accept.trim()) method = 'gzip'; + + // compression method + if (!method) { + for (var i = 0, len = names.length; i < len; ++i) { + if (~accept.indexOf(names[i])) { + method = names[i]; + break; + } + } + } + + // compression method + if (!method) return; + + // compression stream + stream = exports.methods[method](options); + + // header fields + res.setHeader('Content-Encoding', method); + res.removeHeader('Content-Length'); + + // compression + + stream.on('data', function(chunk){ + write.call(res, chunk); + }); + + stream.on('end', function(){ + end.call(res); + }); + + stream.on('drain', function() { + res.emit('drain'); + }); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js b/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js new file mode 100644 index 0000000..5da23f2 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js @@ -0,0 +1,62 @@ + +/*! + * Connect - cookieParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./../utils') + , cookie = require('cookie'); + +/** + * Cookie parser: + * + * Parse _Cookie_ header and populate `req.cookies` + * with an object keyed by the cookie names. Optionally + * you may enabled signed cookie support by passing + * a `secret` string, which assigns `req.secret` so + * it may be used by other middleware. + * + * Examples: + * + * connect() + * .use(connect.cookieParser('optional secret string')) + * .use(function(req, res, next){ + * res.end(JSON.stringify(req.cookies)); + * }) + * + * @param {String} secret + * @return {Function} + * @api public + */ + +module.exports = function cookieParser(secret){ + return function cookieParser(req, res, next) { + if (req.cookies) return next(); + var cookies = req.headers.cookie; + + req.secret = secret; + req.cookies = {}; + req.signedCookies = {}; + + if (cookies) { + try { + req.cookies = cookie.parse(cookies); + if (secret) { + req.signedCookies = utils.parseSignedCookies(req.cookies, secret); + req.signedCookies = utils.parseJSONCookies(req.signedCookies); + } + req.cookies = utils.parseJSONCookies(req.cookies); + } catch (err) { + err.status = 400; + return next(err); + } + } + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js b/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js new file mode 100644 index 0000000..1a23d57 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js @@ -0,0 +1,115 @@ + +/*! + * Connect - cookieSession + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('./../utils') + , Cookie = require('./session/cookie') + , debug = require('debug')('connect:cookieSession') + , signature = require('cookie-signature') + , crc32 = require('buffer-crc32'); + +/** + * Cookie Session: + * + * Cookie session middleware. + * + * var app = connect(); + * app.use(connect.cookieParser()); + * app.use(connect.cookieSession({ secret: 'tobo!', cookie: { maxAge: 60 * 60 * 1000 }})); + * + * Options: + * + * - `key` cookie name defaulting to `connect.sess` + * - `secret` prevents cookie tampering + * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` + * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") + * + * Clearing sessions: + * + * To clear the session simply set its value to `null`, + * `cookieSession()` will then respond with a 1970 Set-Cookie. + * + * req.session = null; + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function cookieSession(options){ + // TODO: utilize Session/Cookie to unify API + options = options || {}; + var key = options.key || 'connect.sess' + , trustProxy = options.proxy; + + return function cookieSession(req, res, next) { + + // req.secret is for backwards compatibility + var secret = options.secret || req.secret; + if (!secret) throw new Error('`secret` option required for cookie sessions'); + + // default session + req.session = {}; + var cookie = req.session.cookie = new Cookie(options.cookie); + + // pathname mismatch + if (0 != req.originalUrl.indexOf(cookie.path)) return next(); + + // cookieParser secret + if (!options.secret && req.secret) { + req.session = req.signedCookies[key] || {}; + } else { + // TODO: refactor + var rawCookie = req.cookies[key]; + if (rawCookie) { + var unsigned = utils.parseSignedCookie(rawCookie, secret); + if (unsigned) { + var originalHash = crc32.signed(unsigned); + req.session = utils.parseJSONCookie(unsigned) || {}; + } + } + } + + res.on('header', function(){ + // removed + if (!req.session) { + debug('clear session'); + cookie.expires = new Date(0); + res.setHeader('Set-Cookie', cookie.serialize(key, '')); + return; + } + + delete req.session.cookie; + + // check security + var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() + , tls = req.connection.encrypted || (trustProxy && 'https' == proto) + , secured = cookie.secure && tls; + + // only send secure cookies via https + if (cookie.secure && !secured) return debug('not secured'); + + // serialize + debug('serializing %j', req.session); + var val = 'j:' + JSON.stringify(req.session); + + // compare hashes, no need to set-cookie if unchanged + if (originalHash == crc32.signed(val)) return debug('unmodified session'); + + // set-cookie + val = 's:' + signature.sign(val, secret); + val = cookie.serialize(key, val); + debug('set-cookie %j', cookie); + res.setHeader('Set-Cookie', val); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/csrf.js b/node_modules/express/node_modules/connect/lib/middleware/csrf.js new file mode 100644 index 0000000..5d5e7c6 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/csrf.js @@ -0,0 +1,73 @@ +/*! + * Connect - csrf + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Anti CSRF: + * + * CRSF protection middleware. + * + * By default this middleware generates a token named "_csrf" + * which should be added to requests which mutate + * state, within a hidden form field, query-string etc. This + * token is validated against the visitor's `req.session._csrf` + * property. + * + * The default `value` function checks `req.body` generated + * by the `bodyParser()` middleware, `req.query` generated + * by `query()`, and the "X-CSRF-Token" header field. + * + * This middleware requires session support, thus should be added + * somewhere _below_ `session()` and `cookieParser()`. + * + * Options: + * + * - `value` a function accepting the request, returning the token + * + * @param {Object} options + * @api public + */ + +module.exports = function csrf(options) { + options = options || {}; + var value = options.value || defaultValue; + + return function(req, res, next){ + // generate CSRF token + var token = req.session._csrf || (req.session._csrf = utils.uid(24)); + + // ignore these methods + if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next(); + + // determine value + var val = value(req); + + // check + if (val != token) return next(403); + + next(); + } +}; + +/** + * Default value function, checking the `req.body` + * and `req.query` for the CSRF token. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +function defaultValue(req) { + return (req.body && req.body._csrf) + || (req.query && req.query._csrf) + || (req.headers['x-csrf-token']); +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/directory.js b/node_modules/express/node_modules/connect/lib/middleware/directory.js new file mode 100644 index 0000000..8fa008c --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/directory.js @@ -0,0 +1,228 @@ + +/*! + * Connect - directory + * Copyright(c) 2011 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +// TODO: icon / style for directories +// TODO: arrow key navigation +// TODO: make icons extensible + +/** + * Module dependencies. + */ + +var fs = require('fs') + , parse = require('url').parse + , path = require('path') + , normalize = path.normalize + , extname = path.extname + , join = path.join; + +/*! + * Icon cache. + */ + +var cache = {}; + +/** + * Directory: + * + * Serve directory listings with the given `root` path. + * + * Options: + * + * - `hidden` display hidden (dot) files. Defaults to false. + * - `icons` display icons. Defaults to false. + * - `filter` Apply this filter function to files. Defaults to false. + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function directory(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('directory() root path required'); + var hidden = options.hidden + , icons = options.icons + , filter = options.filter + , root = normalize(root); + + return function directory(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + + var accept = req.headers.accept || 'text/plain' + , url = parse(req.url) + , dir = decodeURIComponent(url.pathname) + , path = normalize(join(root, dir)) + , originalUrl = parse(req.originalUrl) + , originalDir = decodeURIComponent(originalUrl.pathname) + , showUp = path != root && path != root + '/'; + + // null byte(s), bad request + if (~path.indexOf('\0')) return next(400); + + // malicious path, forbidden + if (0 != path.indexOf(root)) return next(403); + + // check if we have a directory + fs.stat(path, function(err, stat){ + if (err) return 'ENOENT' == err.code + ? next() + : next(err); + + if (!stat.isDirectory()) return next(); + + // fetch files + fs.readdir(path, function(err, files){ + if (err) return next(err); + if (!hidden) files = removeHidden(files); + if (filter) files = files.filter(filter); + files.sort(); + + // content-negotiation + for (var key in exports) { + if (~accept.indexOf(key) || ~accept.indexOf('*/*')) { + exports[key](req, res, files, next, originalDir, showUp, icons); + return; + } + } + + // not acceptable + next(406); + }); + }); + }; +}; + +/** + * Respond with text/html. + */ + +exports.html = function(req, res, files, next, dir, showUp, icons){ + fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){ + if (err) return next(err); + fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){ + if (err) return next(err); + if (showUp) files.unshift('..'); + str = str + .replace('{style}', style) + .replace('{files}', html(files, dir, icons)) + .replace('{directory}', dir) + .replace('{linked-path}', htmlPath(dir)); + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Content-Length', str.length); + res.end(str); + }); + }); +}; + +/** + * Respond with application/json. + */ + +exports.json = function(req, res, files){ + files = JSON.stringify(files); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Respond with text/plain. + */ + +exports.plain = function(req, res, files){ + files = files.join('\n') + '\n'; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', files.length); + res.end(files); +}; + +/** + * Map html `dir`, returning a linked path. + */ + +function htmlPath(dir) { + var curr = []; + return dir.split('/').map(function(part){ + curr.push(part); + return '' + part + ''; + }).join(' / '); +} + +/** + * Map html `files`, returning an html unordered list. + */ + +function html(files, dir, useIcons) { + return '
      ' + files.map(function(file){ + var icon = '' + , classes = []; + + if (useIcons && '..' != file) { + icon = icons[extname(file)] || icons.default; + icon = ''; + classes.push('icon'); + } + + return '
    • ' + + icon + file + '
    • '; + + }).join('\n') + '
    '; +} + +/** + * Load and cache the given `icon`. + * + * @param {String} icon + * @return {String} + * @api private + */ + +function load(icon) { + if (cache[icon]) return cache[icon]; + return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64'); +} + +/** + * Filter "hidden" `files`, aka files + * beginning with a `.`. + * + * @param {Array} files + * @return {Array} + * @api private + */ + +function removeHidden(files) { + return files.filter(function(file){ + return '.' != file[0]; + }); +} + +/** + * Icon map. + */ + +var icons = { + '.js': 'page_white_code_red.png' + , '.c': 'page_white_c.png' + , '.h': 'page_white_h.png' + , '.cc': 'page_white_cplusplus.png' + , '.php': 'page_white_php.png' + , '.rb': 'page_white_ruby.png' + , '.cpp': 'page_white_cplusplus.png' + , '.swf': 'page_white_flash.png' + , '.pdf': 'page_white_acrobat.png' + , 'default': 'page_white.png' +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js new file mode 100644 index 0000000..4a84edc --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js @@ -0,0 +1,86 @@ +/*! + * Connect - errorHandler + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , fs = require('fs'); + +// environment + +var env = process.env.NODE_ENV || 'development'; + +/** + * Error handler: + * + * Development error handler, providing stack traces + * and error message responses for requests accepting text, html, + * or json. + * + * Text: + * + * By default, and when _text/plain_ is accepted a simple stack trace + * or error message will be returned. + * + * JSON: + * + * When _application/json_ is accepted, connect will respond with + * an object in the form of `{ "error": error }`. + * + * HTML: + * + * When accepted connect will output a nice html stack trace. + * + * @return {Function} + * @api public + */ + +exports = module.exports = function errorHandler(){ + return function errorHandler(err, req, res, next){ + if (err.status) res.statusCode = err.status; + if (res.statusCode < 400) res.statusCode = 500; + if ('test' != env) console.error(err.stack); + var accept = req.headers.accept || ''; + // html + if (~accept.indexOf('html')) { + fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){ + fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){ + var stack = (err.stack || '') + .split('\n').slice(1) + .map(function(v){ return '
  • ' + v + '
  • '; }).join(''); + html = html + .replace('{style}', style) + .replace('{stack}', stack) + .replace('{title}', exports.title) + .replace('{statusCode}', res.statusCode) + .replace(/\{error\}/g, utils.escape(err.toString())); + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end(html); + }); + }); + // json + } else if (~accept.indexOf('json')) { + var error = { message: err.message, stack: err.stack }; + for (var prop in err) error[prop] = err[prop]; + var json = JSON.stringify({ error: error }); + res.setHeader('Content-Type', 'application/json'); + res.end(json); + // plain text + } else { + res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' }); + res.end(err.stack); + } + }; +}; + +/** + * Template title, framework authors may override this value. + */ + +exports.title = 'Connect'; diff --git a/node_modules/express/node_modules/connect/lib/middleware/favicon.js b/node_modules/express/node_modules/connect/lib/middleware/favicon.js new file mode 100644 index 0000000..c57bf34 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/favicon.js @@ -0,0 +1,81 @@ + +/*! + * Connect - favicon + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , utils = require('../utils'); + +/** + * Favicon: + * + * By default serves the connect favicon, or the favicon + * located by the given `path`. + * + * Options: + * + * - `maxAge` cache-control max-age directive, defaulting to 1 day + * + * Examples: + * + * Serve default favicon: + * + * connect() + * .use(connect.favicon()) + * + * Serve favicon before logging for brevity: + * + * connect() + * .use(connect.favicon()) + * .use(connect.logger('dev')) + * + * Serve custom favicon: + * + * connect() + * .use(connect.favicon('public/favicon.ico)) + * + * @param {String} path + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function favicon(path, options){ + var options = options || {} + , path = path || __dirname + '/../public/favicon.ico' + , maxAge = options.maxAge || 86400000 + , icon; // favicon cache + + return function favicon(req, res, next){ + if ('/favicon.ico' == req.url) { + if (icon) { + res.writeHead(200, icon.headers); + res.end(icon.body); + } else { + fs.readFile(path, function(err, buf){ + if (err) return next(err); + icon = { + headers: { + 'Content-Type': 'image/x-icon' + , 'Content-Length': buf.length + , 'ETag': '"' + utils.md5(buf) + '"' + , 'Cache-Control': 'public, max-age=' + (maxAge / 1000) + }, + body: buf + }; + res.writeHead(200, icon.headers); + res.end(icon.body); + }); + } + } else { + next(); + } + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/json.js b/node_modules/express/node_modules/connect/lib/middleware/json.js new file mode 100644 index 0000000..200006b --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/json.js @@ -0,0 +1,86 @@ + +/*! + * Connect - json + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , _limit = require('./limit'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * JSON: + * + * Parse JSON request bodies, providing the + * parsed object as `req.body`. + * + * Options: + * + * - `strict` when `false` anything `JSON.parse()` accepts will be parsed + * - `reviver` used as the second "reviver" argument for JSON.parse + * - `limit` byte limit disabled by default + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + var options = options || {} + , strict = options.strict !== false; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function json(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + + if (!utils.hasBody(req)) return next(); + + // check Content-Type + if ('application/json' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk }); + req.on('end', function(){ + var first = buf.trim()[0]; + + if (0 == buf.length) { + return next(400, 'invalid json, empty body'); + } + + if (strict && '{' != first && '[' != first) return next(400, 'invalid json'); + try { + req.body = JSON.parse(buf, options.reviver); + next(); + } catch (err){ + err.body = buf; + err.status = 400; + next(err); + } + }); + }); + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/limit.js b/node_modules/express/node_modules/connect/lib/middleware/limit.js new file mode 100644 index 0000000..614787d --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/limit.js @@ -0,0 +1,55 @@ + +/*! + * Connect - limit + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils'); + +/** + * Limit: + * + * Limit request bodies to the given size in `bytes`. + * + * A string representation of the bytesize may also be passed, + * for example "5mb", "200kb", "1gb", etc. + * + * connect() + * .use(connect.limit('5.5mb')) + * .use(handleImageUpload) + * + * @param {Number|String} bytes + * @return {Function} + * @api public + */ + +module.exports = function limit(bytes){ + if ('string' == typeof bytes) bytes = utils.parseBytes(bytes); + if ('number' != typeof bytes) throw new Error('limit() bytes required'); + return function limit(req, res, next){ + var received = 0 + , len = req.headers['content-length'] + ? parseInt(req.headers['content-length'], 10) + : null; + + // self-awareness + if (req._limit) return next(); + req._limit = true; + + // limit by content-length + if (len && len > bytes) return next(413); + + // limit + req.on('data', function(chunk){ + received += chunk.length; + if (received > bytes) req.destroy(); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/logger.js b/node_modules/express/node_modules/connect/lib/middleware/logger.js new file mode 100644 index 0000000..de72244 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/logger.js @@ -0,0 +1,339 @@ +/*! + * Connect - logger + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var bytes = require('bytes'); + +/*! + * Log buffer. + */ + +var buf = []; + +/*! + * Default log buffer duration. + */ + +var defaultBufferDuration = 1000; + +/** + * Logger: + * + * Log requests with the given `options` or a `format` string. + * + * Options: + * + * - `format` Format string, see below for tokens + * - `stream` Output stream, defaults to _stdout_ + * - `buffer` Buffer duration, defaults to 1000ms when _true_ + * - `immediate` Write log line on request instead of response (for response times) + * + * Tokens: + * + * - `:req[header]` ex: `:req[Accept]` + * - `:res[header]` ex: `:res[Content-Length]` + * - `:http-version` + * - `:response-time` + * - `:remote-addr` + * - `:date` + * - `:method` + * - `:url` + * - `:referrer` + * - `:user-agent` + * - `:status` + * + * Formats: + * + * Pre-defined formats that ship with connect: + * + * - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"' + * - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms' + * - `tiny` ':method :url :status :res[content-length] - :response-time ms' + * - `dev` concise output colored by response status for development use + * + * Examples: + * + * connect.logger() // default + * connect.logger('short') + * connect.logger('tiny') + * connect.logger({ immediate: true, format: 'dev' }) + * connect.logger(':method :url - :referrer') + * connect.logger(':req[content-type] -> :res[content-type]') + * connect.logger(function(tokens, req, res){ return 'some format string' }) + * + * Defining Tokens: + * + * To define a token, simply invoke `connect.logger.token()` with the + * name and a callback function. The value returned is then available + * as ":type" in this case. + * + * connect.logger.token('type', function(req, res){ return req.headers['content-type']; }) + * + * Defining Formats: + * + * All default formats are defined this way, however it's public API as well: + * + * connect.logger.format('name', 'string or function') + * + * @param {String|Function|Object} format or options + * @return {Function} + * @api public + */ + +exports = module.exports = function logger(options) { + if ('object' == typeof options) { + options = options || {}; + } else if (options) { + options = { format: options }; + } else { + options = {}; + } + + // output on request instead of response + var immediate = options.immediate; + + // format name + var fmt = exports[options.format] || options.format || exports.default; + + // compile format + if ('function' != typeof fmt) fmt = compile(fmt); + + // options + var stream = options.stream || process.stdout + , buffer = options.buffer; + + // buffering support + if (buffer) { + var realStream = stream + , interval = 'number' == typeof buffer + ? buffer + : defaultBufferDuration; + + // flush interval + setInterval(function(){ + if (buf.length) { + realStream.write(buf.join('')); + buf.length = 0; + } + }, interval); + + // swap the stream + stream = { + write: function(str){ + buf.push(str); + } + }; + } + + return function logger(req, res, next) { + req._startTime = new Date; + + // immediate + if (immediate) { + var line = fmt(exports, req, res); + if (null == line) return; + stream.write(line + '\n'); + // proxy end to output logging + } else { + var end = res.end; + res.end = function(chunk, encoding){ + res.end = end; + res.end(chunk, encoding); + var line = fmt(exports, req, res); + if (null == line) return; + stream.write(line + '\n'); + }; + } + + + next(); + }; +}; + +/** + * Compile `fmt` into a function. + * + * @param {String} fmt + * @return {Function} + * @api private + */ + +function compile(fmt) { + fmt = fmt.replace(/"/g, '\\"'); + var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){ + return '"\n + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "'; + }) + '";' + return new Function('tokens, req, res', js); +}; + +/** + * Define a token function with the given `name`, + * and callback `fn(req, res)`. + * + * @param {String} name + * @param {Function} fn + * @return {Object} exports for chaining + * @api public + */ + +exports.token = function(name, fn) { + exports[name] = fn; + return this; +}; + +/** + * Define a `fmt` with the given `name`. + * + * @param {String} name + * @param {String|Function} fmt + * @return {Object} exports for chaining + * @api public + */ + +exports.format = function(name, str){ + exports[name] = str; + return this; +}; + +/** + * Default format. + */ + +exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'); + +/** + * Short format. + */ + +exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'); + +/** + * Tiny format. + */ + +exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms'); + +/** + * dev (colored) + */ + +exports.format('dev', function(tokens, req, res){ + var status = res.statusCode + , len = parseInt(res.getHeader('Content-Length'), 10) + , color = 32; + + if (status >= 500) color = 31 + else if (status >= 400) color = 33 + else if (status >= 300) color = 36; + + len = isNaN(len) + ? '' + : len = ' - ' + bytes(len); + + return '\033[90m' + req.method + + ' ' + req.originalUrl + ' ' + + '\033[' + color + 'm' + res.statusCode + + ' \033[90m' + + (new Date - req._startTime) + + 'ms' + len + + '\033[0m'; +}); + +/** + * request url + */ + +exports.token('url', function(req){ + return req.originalUrl || req.url; +}); + +/** + * request method + */ + +exports.token('method', function(req){ + return req.method; +}); + +/** + * response time in milliseconds + */ + +exports.token('response-time', function(req){ + return new Date - req._startTime; +}); + +/** + * UTC date + */ + +exports.token('date', function(){ + return new Date().toUTCString(); +}); + +/** + * response status code + */ + +exports.token('status', function(req, res){ + return res.statusCode; +}); + +/** + * normalized referrer + */ + +exports.token('referrer', function(req){ + return req.headers['referer'] || req.headers['referrer']; +}); + +/** + * remote address + */ + +exports.token('remote-addr', function(req){ + if (req.ip) return req.ip; + var sock = req.socket; + if (sock.socket) return sock.socket.remoteAddress; + return sock.remoteAddress; +}); + +/** + * HTTP version + */ + +exports.token('http-version', function(req){ + return req.httpVersionMajor + '.' + req.httpVersionMinor; +}); + +/** + * UA string + */ + +exports.token('user-agent', function(req){ + return req.headers['user-agent']; +}); + +/** + * request header + */ + +exports.token('req', function(req, res, field){ + return req.headers[field.toLowerCase()]; +}); + +/** + * response header + */ + +exports.token('res', function(req, res, field){ + return (res._headers || {})[field.toLowerCase()]; +}); + diff --git a/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js b/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js new file mode 100644 index 0000000..aaf4014 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js @@ -0,0 +1,40 @@ + +/*! + * Connect - methodOverride + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Method Override: + * + * Provides faux HTTP method support. + * + * Pass an optional `key` to use when checking for + * a method override, othewise defaults to _\_method_. + * The original method is available via `req.originalMethod`. + * + * @param {String} key + * @return {Function} + * @api public + */ + +module.exports = function methodOverride(key){ + key = key || "_method"; + return function methodOverride(req, res, next) { + req.originalMethod = req.originalMethod || req.method; + + // req.body + if (req.body && key in req.body) { + req.method = req.body[key].toUpperCase(); + delete req.body[key]; + // check X-HTTP-Method-Override + } else if (req.headers['x-http-method-override']) { + req.method = req.headers['x-http-method-override'].toUpperCase(); + } + + next(); + }; +}; + diff --git a/node_modules/express/node_modules/connect/lib/middleware/multipart.js b/node_modules/express/node_modules/connect/lib/middleware/multipart.js new file mode 100644 index 0000000..7b26fae --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/multipart.js @@ -0,0 +1,133 @@ +/*! + * Connect - multipart + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var formidable = require('formidable') + , _limit = require('./limit') + , utils = require('../utils') + , qs = require('qs'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * Multipart: + * + * Parse multipart/form-data request bodies, + * providing the parsed object as `req.body` + * and `req.files`. + * + * Configuration: + * + * The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s + * `IncomingForm` object, allowing you to configure the upload directory, + * size limits, etc. For example if you wish to change the upload dir do the following. + * + * app.use(connect.multipart({ uploadDir: path })); + * + * Options: + * + * - `limit` byte limit defaulting to none + * - `defer` defers processing and exposes the Formidable form object as `req.form`. + * `next()` is called without waiting for the form's "end" event. + * This option is useful if you need to bind to the "progress" event, for example. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + options = options || {}; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function multipart(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + req.files = req.files || {}; + + if (!utils.hasBody(req)) return next(); + + // ignore GET + if ('GET' == req.method || 'HEAD' == req.method) return next(); + + // check Content-Type + if ('multipart/form-data' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + + var form = new formidable.IncomingForm + , data = {} + , files = {} + , done; + + Object.keys(options).forEach(function(key){ + form[key] = options[key]; + }); + + function ondata(name, val, data){ + if (Array.isArray(data[name])) { + data[name].push(val); + } else if (data[name]) { + data[name] = [data[name], val]; + } else { + data[name] = val; + } + } + + form.on('field', function(name, val){ + ondata(name, val, data); + }); + + form.on('file', function(name, val){ + ondata(name, val, files); + }); + + form.on('error', function(err){ + if (!options.defer) { + err.status = 400; + next(err); + } + done = true; + }); + + form.on('end', function(){ + if (done) return; + try { + req.body = qs.parse(data); + req.files = qs.parse(files); + if (!options.defer) next(); + } catch (err) { + form.emit('error', err); + } + }); + + form.parse(req); + + if (options.defer) { + req.form = form; + next(); + } + }); + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/query.js b/node_modules/express/node_modules/connect/lib/middleware/query.js new file mode 100644 index 0000000..93fc5d3 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/query.js @@ -0,0 +1,46 @@ +/*! + * Connect - query + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var qs = require('qs') + , parse = require('../utils').parseUrl; + +/** + * Query: + * + * Automatically parse the query-string when available, + * populating the `req.query` object. + * + * Examples: + * + * connect() + * .use(connect.query()) + * .use(function(req, res){ + * res.end(JSON.stringify(req.query)); + * }); + * + * The `options` passed are provided to qs.parse function. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function query(options){ + return function query(req, res, next){ + if (!req.query) { + req.query = ~req.url.indexOf('?') + ? qs.parse(parse(req).query, options) + : {}; + } + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/responseTime.js b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js new file mode 100644 index 0000000..62abc04 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js @@ -0,0 +1,32 @@ + +/*! + * Connect - responseTime + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Reponse time: + * + * Adds the `X-Response-Time` header displaying the response + * duration in milliseconds. + * + * @return {Function} + * @api public + */ + +module.exports = function responseTime(){ + return function(req, res, next){ + var start = new Date; + + if (res._responseTime) return next(); + res._responseTime = true; + + res.on('header', function(){ + var duration = new Date - start; + res.setHeader('X-Response-Time', duration + 'ms'); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session.js b/node_modules/express/node_modules/connect/lib/middleware/session.js new file mode 100644 index 0000000..f97b8d6 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session.js @@ -0,0 +1,352 @@ + +/*! + * Connect - session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Session = require('./session/session') + , debug = require('debug')('connect:session') + , MemoryStore = require('./session/memory') + , signature = require('cookie-signature') + , Cookie = require('./session/cookie') + , Store = require('./session/store') + , utils = require('./../utils') + , parse = utils.parseUrl + , crc32 = require('buffer-crc32'); + +// environment + +var env = process.env.NODE_ENV; + +/** + * Expose the middleware. + */ + +exports = module.exports = session; + +/** + * Expose constructors. + */ + +exports.Store = Store; +exports.Cookie = Cookie; +exports.Session = Session; +exports.MemoryStore = MemoryStore; + +/** + * Warning message for `MemoryStore` usage in production. + */ + +var warning = 'Warning: connection.session() MemoryStore is not\n' + + 'designed for a production environment, as it will leak\n' + + 'memory, and will not scale past a single process.'; + +/** + * Session: + * + * Setup session store with the given `options`. + * + * Session data is _not_ saved in the cookie itself, however + * cookies are used, so we must use the [cookieParser()](cookieParser.html) + * middleware _before_ `session()`. + * + * Examples: + * + * connect() + * .use(connect.cookieParser()) + * .use(connect.session({ secret: 'keyboard cat', key: 'sid', cookie: { secure: true }})) + * + * Options: + * + * - `key` cookie name defaulting to `connect.sid` + * - `store` session store instance + * - `secret` session cookie is signed with this secret to prevent tampering + * - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }` + * - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto") + * + * Cookie option: + * + * By default `cookie.maxAge` is `null`, meaning no "expires" parameter is set + * so the cookie becomes a browser-session cookie. When the user closes the + * browser the cookie (and session) will be removed. + * + * ## req.session + * + * To store or access session data, simply use the request property `req.session`, + * which is (generally) serialized as JSON by the store, so nested objects + * are typically fine. For example below is a user-specific view counter: + * + * connect() + * .use(connect.favicon()) + * .use(connect.cookieParser()) + * .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})) + * .use(function(req, res, next){ + * var sess = req.session; + * if (sess.views) { + * res.setHeader('Content-Type', 'text/html'); + * res.write('

    views: ' + sess.views + '

    '); + * res.write('

    expires in: ' + (sess.cookie.maxAge / 1000) + 's

    '); + * res.end(); + * sess.views++; + * } else { + * sess.views = 1; + * res.end('welcome to the session demo. refresh!'); + * } + * } + * )).listen(3000); + * + * ## Session#regenerate() + * + * To regenerate the session simply invoke the method, once complete + * a new SID and `Session` instance will be initialized at `req.session`. + * + * req.session.regenerate(function(err){ + * // will have a new session here + * }); + * + * ## Session#destroy() + * + * Destroys the session, removing `req.session`, will be re-generated next request. + * + * req.session.destroy(function(err){ + * // cannot access session here + * }); + * + * ## Session#reload() + * + * Reloads the session data. + * + * req.session.reload(function(err){ + * // session updated + * }); + * + * ## Session#save() + * + * Save the session. + * + * req.session.save(function(err){ + * // session saved + * }); + * + * ## Session#touch() + * + * Updates the `.maxAge` property. Typically this is + * not necessary to call, as the session middleware does this for you. + * + * ## Session#cookie + * + * Each session has a unique cookie object accompany it. This allows + * you to alter the session cookie per visitor. For example we can + * set `req.session.cookie.expires` to `false` to enable the cookie + * to remain for only the duration of the user-agent. + * + * ## Session#maxAge + * + * Alternatively `req.session.cookie.maxAge` will return the time + * remaining in milliseconds, which we may also re-assign a new value + * to adjust the `.expires` property appropriately. The following + * are essentially equivalent + * + * var hour = 3600000; + * req.session.cookie.expires = new Date(Date.now() + hour); + * req.session.cookie.maxAge = hour; + * + * For example when `maxAge` is set to `60000` (one minute), and 30 seconds + * has elapsed it will return `30000` until the current request has completed, + * at which time `req.session.touch()` is called to reset `req.session.maxAge` + * to its original value. + * + * req.session.cookie.maxAge; + * // => 30000 + * + * Session Store Implementation: + * + * Every session store _must_ implement the following methods + * + * - `.get(sid, callback)` + * - `.set(sid, session, callback)` + * - `.destroy(sid, callback)` + * + * Recommended methods include, but are not limited to: + * + * - `.length(callback)` + * - `.clear(callback)` + * + * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo. + * + * @param {Object} options + * @return {Function} + * @api public + */ + +function session(options){ + var options = options || {} + , key = options.key || 'connect.sid' + , store = options.store || new MemoryStore + , cookie = options.cookie || {} + , trustProxy = options.proxy + , storeReady = true; + + // notify user that this store is not + // meant for a production environment + if ('production' == env && store instanceof MemoryStore) { + console.warn(warning); + } + + // generates the new session + store.generate = function(req){ + req.sessionID = utils.uid(24); + req.session = new Session(req); + req.session.cookie = new Cookie(cookie); + }; + + store.on('disconnect', function(){ storeReady = false; }); + store.on('connect', function(){ storeReady = true; }); + + return function session(req, res, next) { + // self-awareness + if (req.session) return next(); + + // Handle connection as if there is no session if + // the store has temporarily disconnected etc + if (!storeReady) return debug('store is disconnected'), next(); + + // pathname mismatch + if (0 != req.originalUrl.indexOf(cookie.path || '/')) return next(); + + // backwards compatibility for signed cookies + // req.secret is passed from the cookie parser middleware + var secret = options.secret || req.secret; + + // ensure secret is available or bail + if (!secret) throw new Error('`secret` option required for sessions'); + + // parse url + var originalHash + , originalId; + + // expose store + req.sessionStore = store; + + // grab the session cookie value and check the signature + var rawCookie = req.cookies[key]; + + // get signedCookies for backwards compat with signed cookies + var unsignedCookie = req.signedCookies[key]; + + if (!unsignedCookie && rawCookie) { + unsignedCookie = utils.parseSignedCookie(rawCookie, secret); + } + + // set-cookie + res.on('header', function(){ + if (!req.session) return; + var cookie = req.session.cookie + , proto = (req.headers['x-forwarded-proto'] || '').toLowerCase() + , tls = req.connection.encrypted || (trustProxy && 'https' == proto) + , secured = cookie.secure && tls + , isNew = unsignedCookie != req.sessionID; + + // only send secure cookies via https + if (cookie.secure && !secured) return debug('not secured'); + + // browser-session length cookie + if (null == cookie.expires) { + if (!isNew) return debug('already set browser-session cookie'); + // compare hashes and ids + } else if (originalHash == hash(req.session) && originalId == req.session.id) { + return debug('unmodified session'); + } + + var val = 's:' + signature.sign(req.sessionID, secret); + val = cookie.serialize(key, val); + debug('set-cookie %s', val); + res.setHeader('Set-Cookie', val); + }); + + // proxy end() to commit the session + var end = res.end; + res.end = function(data, encoding){ + res.end = end; + if (!req.session) return res.end(data, encoding); + debug('saving'); + req.session.resetMaxAge(); + req.session.save(function(){ + debug('saved'); + res.end(data, encoding); + }); + }; + + // generate the session + function generate() { + store.generate(req); + } + + // get the sessionID from the cookie + req.sessionID = unsignedCookie; + + // generate a session if the browser doesn't send a sessionID + if (!req.sessionID) { + debug('no SID sent, generating session'); + generate(); + next(); + return; + } + + // generate the session object + var pause = utils.pause(req); + debug('fetching %s', req.sessionID); + store.get(req.sessionID, function(err, sess){ + // proxy to resume() events + var _next = next; + next = function(err){ + _next(err); + pause.resume(); + }; + + // error handling + if (err) { + debug('error'); + if ('ENOENT' == err.code) { + generate(); + next(); + } else { + next(err); + } + // no session + } else if (!sess) { + debug('no session found'); + generate(); + next(); + // populate req.session + } else { + debug('session found'); + store.createSession(req, sess); + originalId = req.sessionID; + originalHash = hash(sess); + next(); + } + }); + }; +}; + +/** + * Hash the given `sess` object omitting changes + * to `.cookie`. + * + * @param {Object} sess + * @return {String} + * @api private + */ + +function hash(sess) { + return crc32.signed(JSON.stringify(sess, function(key, val){ + if ('cookie' != key) return val; + })); +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js b/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js new file mode 100644 index 0000000..e8ff862 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js @@ -0,0 +1,128 @@ + +/*! + * Connect - session - Cookie + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../../utils') + , cookie = require('cookie'); + +/** + * Initialize a new `Cookie` with the given `options`. + * + * @param {IncomingMessage} req + * @param {Object} options + * @api private + */ + +var Cookie = module.exports = function Cookie(options) { + this.path = '/'; + this.maxAge = null; + this.httpOnly = true; + if (options) utils.merge(this, options); + this.originalMaxAge = undefined == this.originalMaxAge + ? this.maxAge + : this.originalMaxAge; +}; + +/*! + * Prototype. + */ + +Cookie.prototype = { + + /** + * Set expires `date`. + * + * @param {Date} date + * @api public + */ + + set expires(date) { + this._expires = date; + this.originalMaxAge = this.maxAge; + }, + + /** + * Get expires `date`. + * + * @return {Date} + * @api public + */ + + get expires() { + return this._expires; + }, + + /** + * Set expires via max-age in `ms`. + * + * @param {Number} ms + * @api public + */ + + set maxAge(ms) { + this.expires = 'number' == typeof ms + ? new Date(Date.now() + ms) + : ms; + }, + + /** + * Get expires max-age in `ms`. + * + * @return {Number} + * @api public + */ + + get maxAge() { + return this.expires instanceof Date + ? this.expires.valueOf() - Date.now() + : this.expires; + }, + + /** + * Return cookie data object. + * + * @return {Object} + * @api private + */ + + get data() { + return { + originalMaxAge: this.originalMaxAge + , expires: this._expires + , secure: this.secure + , httpOnly: this.httpOnly + , domain: this.domain + , path: this.path + } + }, + + /** + * Return a serialized cookie string. + * + * @return {String} + * @api public + */ + + serialize: function(name, val){ + return cookie.serialize(name, val, this.data); + }, + + /** + * Return JSON representation of this cookie. + * + * @return {Object} + * @api private + */ + + toJSON: function(){ + return this.data; + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/memory.js b/node_modules/express/node_modules/connect/lib/middleware/session/memory.js new file mode 100644 index 0000000..fb93939 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/memory.js @@ -0,0 +1,129 @@ + +/*! + * Connect - session - MemoryStore + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Store = require('./store'); + +/** + * Initialize a new `MemoryStore`. + * + * @api public + */ + +var MemoryStore = module.exports = function MemoryStore() { + this.sessions = {}; +}; + +/** + * Inherit from `Store.prototype`. + */ + +MemoryStore.prototype.__proto__ = Store.prototype; + +/** + * Attempt to fetch session by the given `sid`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.get = function(sid, fn){ + var self = this; + process.nextTick(function(){ + var expires + , sess = self.sessions[sid]; + if (sess) { + sess = JSON.parse(sess); + expires = 'string' == typeof sess.cookie.expires + ? new Date(sess.cookie.expires) + : sess.cookie.expires; + if (!expires || new Date < expires) { + fn(null, sess); + } else { + self.destroy(sid, fn); + } + } else { + fn(); + } + }); +}; + +/** + * Commit the given `sess` object associated with the given `sid`. + * + * @param {String} sid + * @param {Session} sess + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.set = function(sid, sess, fn){ + var self = this; + process.nextTick(function(){ + self.sessions[sid] = JSON.stringify(sess); + fn && fn(); + }); +}; + +/** + * Destroy the session associated with the given `sid`. + * + * @param {String} sid + * @api public + */ + +MemoryStore.prototype.destroy = function(sid, fn){ + var self = this; + process.nextTick(function(){ + delete self.sessions[sid]; + fn && fn(); + }); +}; + +/** + * Invoke the given callback `fn` with all active sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.all = function(fn){ + var arr = [] + , keys = Object.keys(this.sessions); + for (var i = 0, len = keys.length; i < len; ++i) { + arr.push(this.sessions[keys[i]]); + } + fn(null, arr); +}; + +/** + * Clear all sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.clear = function(fn){ + this.sessions = {}; + fn && fn(); +}; + +/** + * Fetch number of sessions. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.length = function(fn){ + fn(null, Object.keys(this.sessions).length); +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/session.js b/node_modules/express/node_modules/connect/lib/middleware/session/session.js new file mode 100644 index 0000000..0dd4b40 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/session.js @@ -0,0 +1,116 @@ + +/*! + * Connect - session - Session + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../../utils'); + +/** + * Create a new `Session` with the given request and `data`. + * + * @param {IncomingRequest} req + * @param {Object} data + * @api private + */ + +var Session = module.exports = function Session(req, data) { + Object.defineProperty(this, 'req', { value: req }); + Object.defineProperty(this, 'id', { value: req.sessionID }); + if ('object' == typeof data) utils.merge(this, data); +}; + +/** + * Update reset `.cookie.maxAge` to prevent + * the cookie from expiring when the + * session is still active. + * + * @return {Session} for chaining + * @api public + */ + +Session.prototype.touch = function(){ + return this.resetMaxAge(); +}; + +/** + * Reset `.maxAge` to `.originalMaxAge`. + * + * @return {Session} for chaining + * @api public + */ + +Session.prototype.resetMaxAge = function(){ + this.cookie.maxAge = this.cookie.originalMaxAge; + return this; +}; + +/** + * Save the session data with optional callback `fn(err)`. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.save = function(fn){ + this.req.sessionStore.set(this.id, this, fn || function(){}); + return this; +}; + +/** + * Re-loads the session data _without_ altering + * the maxAge properties. Invokes the callback `fn(err)`, + * after which time if no exception has occurred the + * `req.session` property will be a new `Session` object, + * although representing the same session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.reload = function(fn){ + var req = this.req + , store = this.req.sessionStore; + store.get(this.id, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(new Error('failed to load session')); + store.createSession(req, sess); + fn(); + }); + return this; +}; + +/** + * Destroy `this` session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.destroy = function(fn){ + delete this.req.session; + this.req.sessionStore.destroy(this.id, fn); + return this; +}; + +/** + * Regenerate this request's session. + * + * @param {Function} fn + * @return {Session} for chaining + * @api public + */ + +Session.prototype.regenerate = function(fn){ + this.req.sessionStore.regenerate(this.req, fn); + return this; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/store.js b/node_modules/express/node_modules/connect/lib/middleware/session/store.js new file mode 100644 index 0000000..54294cb --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/session/store.js @@ -0,0 +1,84 @@ + +/*! + * Connect - session - Store + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , Session = require('./session') + , Cookie = require('./cookie'); + +/** + * Initialize abstract `Store`. + * + * @api private + */ + +var Store = module.exports = function Store(options){}; + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Store.prototype.__proto__ = EventEmitter.prototype; + +/** + * Re-generate the given requests's session. + * + * @param {IncomingRequest} req + * @return {Function} fn + * @api public + */ + +Store.prototype.regenerate = function(req, fn){ + var self = this; + this.destroy(req.sessionID, function(err){ + self.generate(req); + fn(err); + }); +}; + +/** + * Load a `Session` instance via the given `sid` + * and invoke the callback `fn(err, sess)`. + * + * @param {String} sid + * @param {Function} fn + * @api public + */ + +Store.prototype.load = function(sid, fn){ + var self = this; + this.get(sid, function(err, sess){ + if (err) return fn(err); + if (!sess) return fn(); + var req = { sessionID: sid, sessionStore: self }; + sess = self.createSession(req, sess); + fn(null, sess); + }); +}; + +/** + * Create session from JSON `sess` data. + * + * @param {IncomingRequest} req + * @param {Object} sess + * @return {Session} + * @api private + */ + +Store.prototype.createSession = function(req, sess){ + var expires = sess.cookie.expires + , orig = sess.cookie.originalMaxAge; + sess.cookie = new Cookie(sess.cookie); + if ('string' == typeof expires) sess.cookie.expires = new Date(expires); + sess.cookie.originalMaxAge = orig; + req.session = new Session(req, sess); + return req.session; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/static.js b/node_modules/express/node_modules/connect/lib/middleware/static.js new file mode 100644 index 0000000..bb29d07 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/static.js @@ -0,0 +1,94 @@ + +/*! + * Connect - static + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var send = require('send') + , utils = require('../utils') + , parse = utils.parseUrl + , url = require('url'); + +/** + * Static: + * + * Static file server with the given `root` path. + * + * Examples: + * + * var oneDay = 86400000; + * + * connect() + * .use(connect.static(__dirname + '/public')) + * + * connect() + * .use(connect.static(__dirname + '/public', { maxAge: oneDay })) + * + * Options: + * + * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0 + * - `hidden` Allow transfer of hidden files. defaults to false + * - `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to true + * + * @param {String} root + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function static(root, options){ + options = options || {}; + + // root required + if (!root) throw new Error('static() root path required'); + + // default redirect + var redirect = false !== options.redirect; + + return function static(req, res, next) { + if ('GET' != req.method && 'HEAD' != req.method) return next(); + var path = parse(req).pathname; + var pause = utils.pause(req); + + function resume() { + next(); + pause.resume(); + } + + function directory() { + if (!redirect) return resume(); + var pathname = url.parse(req.originalUrl).pathname; + res.statusCode = 301; + res.setHeader('Location', pathname + '/'); + res.end('Redirecting to ' + utils.escape(pathname) + '/'); + } + + function error(err) { + if (404 == err.status) return resume(); + next(err); + } + + send(req, path) + .maxage(options.maxAge || 0) + .root(root) + .hidden(options.hidden) + .on('error', error) + .on('directory', directory) + .pipe(res); + }; +}; + +/** + * Expose mime module. + * + * If you wish to extend the mime table use this + * reference to the "mime" module in the npm registry. + */ + +exports.mime = send.mime; diff --git a/node_modules/express/node_modules/connect/lib/middleware/staticCache.js b/node_modules/express/node_modules/connect/lib/middleware/staticCache.js new file mode 100644 index 0000000..7354a8f --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/staticCache.js @@ -0,0 +1,231 @@ + +/*! + * Connect - staticCache + * Copyright(c) 2011 Sencha Inc. + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , Cache = require('../cache') + , fresh = require('fresh'); + +/** + * Static cache: + * + * Enables a memory cache layer on top of + * the `static()` middleware, serving popular + * static files. + * + * By default a maximum of 128 objects are + * held in cache, with a max of 256k each, + * totalling ~32mb. + * + * A Least-Recently-Used (LRU) cache algo + * is implemented through the `Cache` object, + * simply rotating cache objects as they are + * hit. This means that increasingly popular + * objects maintain their positions while + * others get shoved out of the stack and + * garbage collected. + * + * Benchmarks: + * + * static(): 2700 rps + * node-static: 5300 rps + * static() + staticCache(): 7500 rps + * + * Options: + * + * - `maxObjects` max cache objects [128] + * - `maxLength` max cache object length 256kb + * + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function staticCache(options){ + var options = options || {} + , cache = new Cache(options.maxObjects || 128) + , maxlen = options.maxLength || 1024 * 256; + + console.warn('connect.staticCache() is deprecated and will be removed in 3.0'); + console.warn('use varnish or similar reverse proxy caches.'); + + return function staticCache(req, res, next){ + var key = cacheKey(req) + , ranges = req.headers.range + , hasCookies = req.headers.cookie + , hit = cache.get(key); + + // cache static + // TODO: change from staticCache() -> cache() + // and make this work for any request + req.on('static', function(stream){ + var headers = res._headers + , cc = utils.parseCacheControl(headers['cache-control'] || '') + , contentLength = headers['content-length'] + , hit; + + // dont cache set-cookie responses + if (headers['set-cookie']) return hasCookies = true; + + // dont cache when cookies are present + if (hasCookies) return; + + // ignore larger files + if (!contentLength || contentLength > maxlen) return; + + // don't cache partial files + if (headers['content-range']) return; + + // dont cache items we shouldn't be + // TODO: real support for must-revalidate / no-cache + if ( cc['no-cache'] + || cc['no-store'] + || cc['private'] + || cc['must-revalidate']) return; + + // if already in cache then validate + if (hit = cache.get(key)){ + if (headers.etag == hit[0].etag) { + hit[0].date = new Date; + return; + } else { + cache.remove(key); + } + } + + // validation notifiactions don't contain a steam + if (null == stream) return; + + // add the cache object + var arr = []; + + // store the chunks + stream.on('data', function(chunk){ + arr.push(chunk); + }); + + // flag it as complete + stream.on('end', function(){ + var cacheEntry = cache.add(key); + delete headers['x-cache']; // Clean up (TODO: others) + cacheEntry.push(200); + cacheEntry.push(headers); + cacheEntry.push.apply(cacheEntry, arr); + }); + }); + + if (req.method == 'GET' || req.method == 'HEAD') { + if (ranges) { + next(); + } else if (!hasCookies && hit && !mustRevalidate(req, hit)) { + res.setHeader('X-Cache', 'HIT'); + respondFromCache(req, res, hit); + } else { + res.setHeader('X-Cache', 'MISS'); + next(); + } + } else { + next(); + } + } +}; + +/** + * Respond with the provided cached value. + * TODO: Assume 200 code, that's iffy. + * + * @param {Object} req + * @param {Object} res + * @param {Object} cacheEntry + * @return {String} + * @api private + */ + +function respondFromCache(req, res, cacheEntry) { + var status = cacheEntry[0] + , headers = utils.merge({}, cacheEntry[1]) + , content = cacheEntry.slice(2); + + headers.age = (new Date - new Date(headers.date)) / 1000 || 0; + + switch (req.method) { + case 'HEAD': + res.writeHead(status, headers); + res.end(); + break; + case 'GET': + if (utils.conditionalGET(req) && fresh(req.headers, headers)) { + headers['content-length'] = 0; + res.writeHead(304, headers); + res.end(); + } else { + res.writeHead(status, headers); + + function write() { + while (content.length) { + if (false === res.write(content.shift())) { + res.once('drain', write); + return; + } + } + res.end(); + } + + write(); + } + break; + default: + // This should never happen. + res.writeHead(500, ''); + res.end(); + } +} + +/** + * Determine whether or not a cached value must be revalidated. + * + * @param {Object} req + * @param {Object} cacheEntry + * @return {String} + * @api private + */ + +function mustRevalidate(req, cacheEntry) { + var cacheHeaders = cacheEntry[1] + , reqCC = utils.parseCacheControl(req.headers['cache-control'] || '') + , cacheCC = utils.parseCacheControl(cacheHeaders['cache-control'] || '') + , cacheAge = (new Date - new Date(cacheHeaders.date)) / 1000 || 0; + + if ( cacheCC['no-cache'] + || cacheCC['must-revalidate'] + || cacheCC['proxy-revalidate']) return true; + + if (reqCC['no-cache']) return true; + + if (null != reqCC['max-age']) return reqCC['max-age'] < cacheAge; + + if (null != cacheCC['max-age']) return cacheCC['max-age'] < cacheAge; + + return false; +} + +/** + * The key to use in the cache. For now, this is the URL path and query. + * + * 'http://example.com?key=value' -> '/?key=value' + * + * @param {Object} req + * @return {String} + * @api private + */ + +function cacheKey(req) { + return utils.parseUrl(req).path; +} diff --git a/node_modules/express/node_modules/connect/lib/middleware/timeout.js b/node_modules/express/node_modules/connect/lib/middleware/timeout.js new file mode 100644 index 0000000..a6dc087 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/timeout.js @@ -0,0 +1,56 @@ + +/*! + * Connect - timeout + * Ported from https://github.com/LearnBoost/connect-timeout + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var debug = require('debug')('connect:timeout'); + +/** + * Timeout: + * + * Times out the request in `ms`, defaulting to `5000`. The + * method `req.clearTimeout()` is added to revert this behaviour + * programmatically within your application's middleware, routes, etc. + * + * The timeout error is passed to `next()` so that you may customize + * the response behaviour. This error has the `.timeout` property as + * well as `.status == 408`. + * + * @param {Number} ms + * @return {Function} + * @api public + */ + +module.exports = function timeout(ms) { + ms = ms || 5000; + + return function(req, res, next) { + var id = setTimeout(function(){ + req.emit('timeout', ms); + }, ms); + + req.on('timeout', function(){ + if (req.headerSent) return debug('response started, cannot timeout'); + var err = new Error('Response timeout'); + err.timeout = ms; + err.status = 503; + next(err); + }); + + req.clearTimeout = function(){ + clearTimeout(id); + }; + + res.on('header', function(){ + clearTimeout(id); + }); + + next(); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js b/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js new file mode 100644 index 0000000..cceafc0 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js @@ -0,0 +1,78 @@ + +/*! + * Connect - urlencoded + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , _limit = require('./limit') + , qs = require('qs'); + +/** + * noop middleware. + */ + +function noop(req, res, next) { + next(); +} + +/** + * Urlencoded: + * + * Parse x-ww-form-urlencoded request bodies, + * providing the parsed object as `req.body`. + * + * Options: + * + * - `limit` byte limit disabled by default + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function(options){ + options = options || {}; + + var limit = options.limit + ? _limit(options.limit) + : noop; + + return function urlencoded(req, res, next) { + if (req._body) return next(); + req.body = req.body || {}; + + if (!utils.hasBody(req)) return next(); + + // check Content-Type + if ('application/x-www-form-urlencoded' != utils.mime(req)) return next(); + + // flag as parsed + req._body = true; + + // parse + limit(req, res, function(err){ + if (err) return next(err); + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk }); + req.on('end', function(){ + try { + req.body = buf.length + ? qs.parse(buf, options) + : {}; + next(); + } catch (err){ + err.body = buf; + next(err); + } + }); + }); + } +}; diff --git a/node_modules/express/node_modules/connect/lib/middleware/vhost.js b/node_modules/express/node_modules/connect/lib/middleware/vhost.js new file mode 100644 index 0000000..897a9d8 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/middleware/vhost.js @@ -0,0 +1,40 @@ + +/*! + * Connect - vhost + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Vhost: + * + * Setup vhost for the given `hostname` and `server`. + * + * connect() + * .use(connect.vhost('foo.com', fooApp)) + * .use(connect.vhost('bar.com', barApp)) + * .use(connect.vhost('*.com', mainApp)) + * + * The `server` may be a Connect server or + * a regular Node `http.Server`. + * + * @param {String} hostname + * @param {Server} server + * @return {Function} + * @api public + */ + +module.exports = function vhost(hostname, server){ + if (!hostname) throw new Error('vhost hostname required'); + if (!server) throw new Error('vhost server required'); + var regexp = new RegExp('^' + hostname.replace(/[*]/g, '(.*?)') + '$', 'i'); + if (server.onvhost) server.onvhost(hostname); + return function vhost(req, res, next){ + if (!req.headers.host) return next(); + var host = req.headers.host.split(':')[0]; + if (!regexp.test(host)) return next(); + if ('function' == typeof server) return server(req, res, next); + server.emit('request', req, res); + }; +}; diff --git a/node_modules/express/node_modules/connect/lib/patch.js b/node_modules/express/node_modules/connect/lib/patch.js new file mode 100644 index 0000000..7cf0012 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/patch.js @@ -0,0 +1,79 @@ + +/*! + * Connect + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , res = http.ServerResponse.prototype + , setHeader = res.setHeader + , _renderHeaders = res._renderHeaders + , writeHead = res.writeHead; + +// apply only once + +if (!res._hasConnectPatch) { + + /** + * Provide a public "header sent" flag + * until node does. + * + * @return {Boolean} + * @api public + */ + + res.__defineGetter__('headerSent', function(){ + return this._header; + }); + + /** + * Set header `field` to `val`, special-casing + * the `Set-Cookie` field for multiple support. + * + * @param {String} field + * @param {String} val + * @api public + */ + + res.setHeader = function(field, val){ + var key = field.toLowerCase() + , prev; + + // special-case Set-Cookie + if (this._headers && 'set-cookie' == key) { + if (prev = this.getHeader(field)) { + val = Array.isArray(prev) + ? prev.concat(val) + : [prev, val]; + } + // charset + } else if ('content-type' == key && this.charset) { + val += '; charset=' + this.charset; + } + + return setHeader.call(this, field, val); + }; + + /** + * Proxy to emit "header" event. + */ + + res._renderHeaders = function(){ + if (!this._emittedHeader) this.emit('header'); + this._emittedHeader = true; + return _renderHeaders.call(this); + }; + + res.writeHead = function(){ + if (!this._emittedHeader) this.emit('header'); + this._emittedHeader = true; + return writeHead.apply(this, arguments); + }; + + res._hasConnectPatch = true; +} diff --git a/node_modules/express/node_modules/connect/lib/proto.js b/node_modules/express/node_modules/connect/lib/proto.js new file mode 100644 index 0000000..889c237 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/proto.js @@ -0,0 +1,239 @@ + +/*! + * Connect - HTTPServer + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , utils = require('./utils') + , debug = require('debug')('connect:dispatcher'); + +// prototype + +var app = module.exports = {}; + +// environment + +var env = process.env.NODE_ENV || 'development'; + +/** + * Utilize the given middleware `handle` to the given `route`, + * defaulting to _/_. This "route" is the mount-point for the + * middleware, when given a value other than _/_ the middleware + * is only effective when that segment is present in the request's + * pathname. + * + * For example if we were to mount a function at _/admin_, it would + * be invoked on _/admin_, and _/admin/settings_, however it would + * not be invoked for _/_, or _/posts_. + * + * Examples: + * + * var app = connect(); + * app.use(connect.favicon()); + * app.use(connect.logger()); + * app.use(connect.static(__dirname + '/public')); + * + * If we wanted to prefix static files with _/public_, we could + * "mount" the `static()` middleware: + * + * app.use('/public', connect.static(__dirname + '/public')); + * + * This api is chainable, so the following is valid: + * + * connect() + * .use(connect.favicon()) + * .use(connect.logger()) + * .use(connect.static(__dirname + '/public')) + * .listen(3000); + * + * @param {String|Function|Server} route, callback or server + * @param {Function|Server} callback or server + * @return {Server} for chaining + * @api public + */ + +app.use = function(route, fn){ + // default route to '/' + if ('string' != typeof route) { + fn = route; + route = '/'; + } + + // wrap sub-apps + if ('function' == typeof fn.handle) { + var server = fn; + fn.route = route; + fn = function(req, res, next){ + server.handle(req, res, next); + }; + } + + // wrap vanilla http.Servers + if (fn instanceof http.Server) { + fn = fn.listeners('request')[0]; + } + + // strip trailing slash + if ('/' == route[route.length - 1]) { + route = route.slice(0, -1); + } + + // add the middleware + debug('use %s %s', route || '/', fn.name || 'anonymous'); + this.stack.push({ route: route, handle: fn }); + + return this; +}; + +/** + * Handle server requests, punting them down + * the middleware stack. + * + * @api private + */ + +app.handle = function(req, res, out) { + var stack = this.stack + , fqdn = ~req.url.indexOf('://') + , removed = '' + , slashAdded = false + , index = 0; + + function next(err, msg) { + var layer, path, status, c; + + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + req.url = removed + req.url; + req.originalUrl = req.originalUrl || req.url; + removed = ''; + + // next(status, msg) support + if (typeof err === 'number') { + var status = err; + var name = http.STATUS_CODES[status]; + err = new Error(msg || name); + err.name = name; + err.status = status; + } + + // next callback + layer = stack[index++]; + + // all done + if (!layer || res.headerSent) { + // delegate to parent + if (out) return out(err); + + // unhandled error + if (err) { + // default to 500 + if (res.statusCode < 400) res.statusCode = 500; + debug('default %s', res.statusCode); + + // respect err.status + if (err.status) res.statusCode = err.status; + + // production gets a basic error message + var msg = 'production' == env + ? http.STATUS_CODES[res.statusCode] + : err.stack || err.toString(); + + // log to stderr in a non-test env + if ('test' != env) console.error(err.stack || err.toString()); + if (res.headerSent) return req.socket.destroy(); + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', Buffer.byteLength(msg)); + if ('HEAD' == req.method) return res.end(); + res.end(msg); + } else { + debug('default 404'); + res.statusCode = 404; + res.setHeader('Content-Type', 'text/plain'); + if ('HEAD' == req.method) return res.end(); + res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl)); + } + return; + } + + try { + path = utils.parseUrl(req).pathname; + if (undefined == path) path = '/'; + + // skip this layer if the route doesn't match. + if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err); + + c = path[layer.route.length]; + if (c && '/' != c && '.' != c) return next(err); + + // Call the layer handler + // Trim off the part of the url that matches the route + removed = layer.route; + req.url = req.url.substr(removed.length); + + // Ensure leading slash + if (!fqdn && '/' != req.url[0]) { + req.url = '/' + req.url; + slashAdded = true; + } + + debug('%s', layer.handle.name || 'anonymous'); + var arity = layer.handle.length; + if (err) { + if (arity === 4) { + layer.handle(err, req, res, next); + } else { + next(err); + } + } else if (arity < 4) { + layer.handle(req, res, next); + } else { + next(); + } + } catch (e) { + next(e); + } + } + next(); +}; + +/** + * Listen for connections. + * + * This method takes the same arguments + * as node's `http.Server#listen()`. + * + * HTTP and HTTPS: + * + * If you run your application both as HTTP + * and HTTPS you may wrap them individually, + * since your Connect "server" is really just + * a JavaScript `Function`. + * + * var connect = require('connect') + * , http = require('http') + * , https = require('https'); + * + * var app = connect(); + * + * http.createServer(app).listen(80); + * https.createServer(options, app).listen(443); + * + * @return {http.Server} + * @api public + */ + +app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); +}; diff --git a/node_modules/express/node_modules/connect/lib/public/directory.html b/node_modules/express/node_modules/connect/lib/public/directory.html new file mode 100644 index 0000000..2d63704 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/directory.html @@ -0,0 +1,81 @@ + + + + + listing directory {directory} + + + + + +
    +

    {linked-path}

    + {files} +
    + + \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/lib/public/error.html b/node_modules/express/node_modules/connect/lib/public/error.html new file mode 100644 index 0000000..a6d3faf --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/error.html @@ -0,0 +1,14 @@ + + + + {error} + + + +
    +

    {title}

    +

    {statusCode} {error}

    +
      {stack}
    +
    + + diff --git a/node_modules/express/node_modules/connect/lib/public/favicon.ico b/node_modules/express/node_modules/connect/lib/public/favicon.ico new file mode 100644 index 0000000..895fc96 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/favicon.ico differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page.png b/node_modules/express/node_modules/connect/lib/public/icons/page.png new file mode 100644 index 0000000..03ddd79 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_add.png b/node_modules/express/node_modules/connect/lib/public/icons/page_add.png new file mode 100644 index 0000000..d5bfa07 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_add.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png b/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png new file mode 100644 index 0000000..89ee2da Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_attach.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_code.png b/node_modules/express/node_modules/connect/lib/public/icons/page_code.png new file mode 100644 index 0000000..f7ea904 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_code.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png b/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png new file mode 100644 index 0000000..195dc6d Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_copy.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png b/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png new file mode 100644 index 0000000..3141467 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_delete.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png b/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png new file mode 100644 index 0000000..046811e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_edit.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_error.png b/node_modules/express/node_modules/connect/lib/public/icons/page_error.png new file mode 100644 index 0000000..f07f449 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_error.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png b/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png new file mode 100644 index 0000000..eb6158e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_excel.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_find.png b/node_modules/express/node_modules/connect/lib/public/icons/page_find.png new file mode 100644 index 0000000..2f19388 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_find.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png b/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png new file mode 100644 index 0000000..8e83281 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_gear.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_go.png b/node_modules/express/node_modules/connect/lib/public/icons/page_go.png new file mode 100644 index 0000000..80fe1ed Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_go.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_green.png b/node_modules/express/node_modules/connect/lib/public/icons/page_green.png new file mode 100644 index 0000000..de8e003 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_green.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_key.png b/node_modules/express/node_modules/connect/lib/public/icons/page_key.png new file mode 100644 index 0000000..d6626cb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_key.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png b/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png new file mode 100644 index 0000000..7e56870 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_lightning.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_link.png b/node_modules/express/node_modules/connect/lib/public/icons/page_link.png new file mode 100644 index 0000000..312eab0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_link.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png b/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png new file mode 100644 index 0000000..246a2f0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_paintbrush.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png b/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png new file mode 100644 index 0000000..968f073 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_paste.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_red.png b/node_modules/express/node_modules/connect/lib/public/icons/page_red.png new file mode 100644 index 0000000..0b18247 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_red.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png b/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png new file mode 100644 index 0000000..cf347c7 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_refresh.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_save.png b/node_modules/express/node_modules/connect/lib/public/icons/page_save.png new file mode 100644 index 0000000..caea546 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_save.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white.png new file mode 100644 index 0000000..8b8b1ca Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png new file mode 100644 index 0000000..8f8095e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_acrobat.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png new file mode 100644 index 0000000..159b240 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_actionscript.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png new file mode 100644 index 0000000..aa23dde Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_add.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png new file mode 100644 index 0000000..34a05cc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_c.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png new file mode 100644 index 0000000..f501a59 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_camera.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png new file mode 100644 index 0000000..848bdaf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cd.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png new file mode 100644 index 0000000..0c76bd1 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png new file mode 100644 index 0000000..87a6914 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_code_red.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000..c66011f Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_coldfusion.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png new file mode 100644 index 0000000..2b6b100 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_compressed.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png new file mode 100644 index 0000000..a9f31a2 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_copy.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png new file mode 100644 index 0000000..a87cf84 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cplusplus.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png new file mode 100644 index 0000000..ffb8fc9 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_csharp.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png new file mode 100644 index 0000000..0a7d6f4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_cup.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png new file mode 100644 index 0000000..bddba1f Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_database.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png new file mode 100644 index 0000000..af1ecaf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_delete.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png new file mode 100644 index 0000000..4cc537a Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_dvd.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png new file mode 100644 index 0000000..b93e776 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_edit.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png new file mode 100644 index 0000000..9fc5a0a Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_error.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png new file mode 100644 index 0000000..b977d7e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_excel.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png new file mode 100644 index 0000000..5818436 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_find.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png new file mode 100644 index 0000000..5769120 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_flash.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png new file mode 100644 index 0000000..8d719df Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_freehand.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png new file mode 100644 index 0000000..106f5aa Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_gear.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png new file mode 100644 index 0000000..e4a1ecb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_get.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png new file mode 100644 index 0000000..7e62a92 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_go.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png new file mode 100644 index 0000000..e902abb Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_h.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png new file mode 100644 index 0000000..1d2d0a4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_horizontal.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png new file mode 100644 index 0000000..d616484 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_key.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png new file mode 100644 index 0000000..7215d1e Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_lightning.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png new file mode 100644 index 0000000..bf7bd1c Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_link.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png new file mode 100644 index 0000000..f6b74cc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_magnify.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png new file mode 100644 index 0000000..d3fffb6 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_medal.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png new file mode 100644 index 0000000..a65bcb3 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_office.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png new file mode 100644 index 0000000..23a37b8 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paint.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png new file mode 100644 index 0000000..f907e44 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paintbrush.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png new file mode 100644 index 0000000..5b2cbb3 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_paste.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png new file mode 100644 index 0000000..7868a25 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_php.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png new file mode 100644 index 0000000..134b669 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_picture.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000..c4eff03 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_powerpoint.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png new file mode 100644 index 0000000..884ffd6 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_put.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png new file mode 100644 index 0000000..f59b7c4 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_ruby.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png new file mode 100644 index 0000000..44084ad Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_stack.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png new file mode 100644 index 0000000..3a1441c Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_star.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png new file mode 100644 index 0000000..e770829 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_swoosh.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png new file mode 100644 index 0000000..813f712 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png new file mode 100644 index 0000000..d9cf132 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_text_width.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png new file mode 100644 index 0000000..52699bf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_tux.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png new file mode 100644 index 0000000..4a05955 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_vector.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png new file mode 100644 index 0000000..a0a433d Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_visualstudio.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png new file mode 100644 index 0000000..1eb8809 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_width.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png new file mode 100644 index 0000000..ae8ecbf Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_word.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png new file mode 100644 index 0000000..6ed2490 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_world.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png new file mode 100644 index 0000000..fecadd0 Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_wrench.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png b/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png new file mode 100644 index 0000000..fd4bbcc Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_white_zip.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_word.png b/node_modules/express/node_modules/connect/lib/public/icons/page_word.png new file mode 100644 index 0000000..834cdfa Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_word.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/icons/page_world.png b/node_modules/express/node_modules/connect/lib/public/icons/page_world.png new file mode 100644 index 0000000..b8895dd Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/icons/page_world.png differ diff --git a/node_modules/express/node_modules/connect/lib/public/style.css b/node_modules/express/node_modules/connect/lib/public/style.css new file mode 100644 index 0000000..32b6507 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/public/style.css @@ -0,0 +1,141 @@ +body { + margin: 0; + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + margin: 0; + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul { + margin: 0; + padding: 0; +} +ul li { + margin: 5px 0; + padding: 3px 8px; + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 500px; +} +ul#files li { + padding: 0; +} +ul#files li img { + position: absolute; + top: 5px; + left: 5px; +} +ul#files li a { + position: relative; + display: block; + margin: 1px; + width: 30%; + height: 25px; + line-height: 25px; + text-indent: 8px; + float: left; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + text-overflow: ellipsis; +} +ul#files li a.icon { + text-indent: 25px; +} +ul#files li a:focus, +ul#files li a:hover { + outline: none; + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} diff --git a/node_modules/express/node_modules/connect/lib/utils.js b/node_modules/express/node_modules/connect/lib/utils.js new file mode 100644 index 0000000..47b30e0 --- /dev/null +++ b/node_modules/express/node_modules/connect/lib/utils.js @@ -0,0 +1,370 @@ + +/*! + * Connect - utils + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var http = require('http') + , crypto = require('crypto') + , parse = require('url').parse + , signature = require('cookie-signature'); + +/** + * Return `true` if the request has a body, otherwise return `false`. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.hasBody = function(req) { + return 'transfer-encoding' in req.headers || 'content-length' in req.headers; +}; + +/** + * Extract the mime type from the given request's + * _Content-Type_ header. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +exports.mime = function(req) { + var str = req.headers['content-type'] || ''; + return str.split(';')[0]; +}; + +/** + * Return md5 hash of the given string and optional encoding, + * defaulting to hex. + * + * utils.md5('wahoo'); + * // => "e493298061761236c96b02ea6aa8a2ad" + * + * @param {String} str + * @param {String} encoding + * @return {String} + * @api private + */ + +exports.md5 = function(str, encoding){ + return crypto + .createHash('md5') + .update(str) + .digest(encoding || 'hex'); +}; + +/** + * Merge object b with object a. + * + * var a = { foo: 'bar' } + * , b = { bar: 'baz' }; + * + * utils.merge(a, b); + * // => { foo: 'bar', bar: 'baz' } + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api private + */ + +exports.merge = function(a, b){ + if (a && b) { + for (var key in b) { + a[key] = b[key]; + } + } + return a; +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + + +/** + * Return a unique identifier with the given `len`. + * + * utils.uid(10); + * // => "FDaS435D2z" + * + * @param {Number} len + * @return {String} + * @api private + */ + +exports.uid = function(len) { + return crypto.randomBytes(Math.ceil(len * 3 / 4)) + .toString('base64') + .slice(0, len); +}; + +/** + * Sign the given `val` with `secret`. + * + * @param {String} val + * @param {String} secret + * @return {String} + * @api private + */ + +exports.sign = function(val, secret){ + console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature') + return val + '.' + crypto + .createHmac('sha256', secret) + .update(val) + .digest('base64') + .replace(/=+$/, ''); +}; + +/** + * Unsign and decode the given `val` with `secret`, + * returning `false` if the signature is invalid. + * + * @param {String} val + * @param {String} secret + * @return {String|Boolean} + * @api private + */ + +exports.unsign = function(val, secret){ + console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature') + var str = val.slice(0, val.lastIndexOf('.')); + return exports.sign(str, secret) == val + ? str + : false; +}; + +/** + * Parse signed cookies, returning an object + * containing the decoded key/value pairs, + * while removing the signed key from `obj`. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseSignedCookies = function(obj, secret){ + var ret = {}; + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + if (0 == val.indexOf('s:')) { + val = signature.unsign(val.slice(2), secret); + if (val) { + ret[key] = val; + delete obj[key]; + } + } + }); + return ret; +}; + +/** + * Parse a signed cookie string, return the decoded value + * + * @param {String} str signed cookie string + * @param {String} secret + * @return {String} decoded value + * @api private + */ + +exports.parseSignedCookie = function(str, secret){ + return 0 == str.indexOf('s:') + ? signature.unsign(str.slice(2), secret) + : str; +}; + +/** + * Parse JSON cookies. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.parseJSONCookies = function(obj){ + Object.keys(obj).forEach(function(key){ + var val = obj[key]; + var res = exports.parseJSONCookie(val); + if (res) obj[key] = res; + }); + return obj; +}; + +/** + * Parse JSON cookie string + * + * @param {String} str + * @return {Object} Parsed object or null if not json cookie + * @api private + */ + +exports.parseJSONCookie = function(str) { + if (0 == str.indexOf('j:')) { + try { + return JSON.parse(str.slice(2)); + } catch (err) { + // no op + } + } +}; + +/** + * Pause `data` and `end` events on the given `obj`. + * Middleware performing async tasks _should_ utilize + * this utility (or similar), to re-emit data once + * the async operation has completed, otherwise these + * events may be lost. + * + * var pause = utils.pause(req); + * fs.readFile(path, function(){ + * next(); + * pause.resume(); + * }); + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +exports.pause = require('pause'); + +/** + * Strip `Content-*` headers from `res`. + * + * @param {ServerResponse} res + * @api private + */ + +exports.removeContentHeaders = function(res){ + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Check if `req` is a conditional GET request. + * + * @param {IncomingMessage} req + * @return {Boolean} + * @api private + */ + +exports.conditionalGET = function(req) { + return req.headers['if-modified-since'] + || req.headers['if-none-match']; +}; + +/** + * Respond with 401 "Unauthorized". + * + * @param {ServerResponse} res + * @param {String} realm + * @api private + */ + +exports.unauthorized = function(res, realm) { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); + res.end('Unauthorized'); +}; + +/** + * Respond with 304 "Not Modified". + * + * @param {ServerResponse} res + * @param {Object} headers + * @api private + */ + +exports.notModified = function(res) { + exports.removeContentHeaders(res); + res.statusCode = 304; + res.end(); +}; + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * Parse the given Cache-Control `str`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +exports.parseCacheControl = function(str){ + var directives = str.split(',') + , obj = {}; + + for(var i = 0, len = directives.length; i < len; i++) { + var parts = directives[i].split('=') + , key = parts.shift().trim() + , val = parseInt(parts.shift(), 10); + + obj[key] = isNaN(val) ? true : val; + } + + return obj; +}; + +/** + * Parse the `req` url with memoization. + * + * @param {ServerRequest} req + * @return {Object} + * @api private + */ + +exports.parseUrl = function(req){ + var parsed = req._parsedUrl; + if (parsed && parsed.href == req.url) { + return parsed; + } else { + return req._parsedUrl = parse(req.url); + } +}; + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api private + */ + +exports.parseBytes = require('bytes'); diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore b/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/History.md b/node_modules/express/node_modules/connect/node_modules/bytes/History.md new file mode 100644 index 0000000..db1f759 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/History.md @@ -0,0 +1,5 @@ + +0.1.0 / 2012-07-04 +================== + + * add bytes to string conversion [yields] diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/Makefile b/node_modules/express/node_modules/connect/node_modules/bytes/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md b/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md new file mode 100644 index 0000000..9325d5b --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md @@ -0,0 +1,51 @@ +# node-bytes + + Byte string parser / formatter. + +## Example: + +```js +bytes('1kb') +// => 1024 + +bytes('2mb') +// => 2097152 + +bytes('1gb') +// => 1073741824 + +bytes(1073741824) +// => 1gb +``` + +## Installation + +``` +$ npm install bytes +$ component install visionmedia/bytes.js +``` + +## License + +(The MIT License) + +Copyright (c) 2012 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. diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/component.json b/node_modules/express/node_modules/connect/node_modules/bytes/component.json new file mode 100644 index 0000000..76a6057 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/component.json @@ -0,0 +1,7 @@ +{ + "name": "bytes", + "description": "byte size string parser / serializer", + "keywords": ["bytes", "utility"], + "version": "0.1.0", + "scripts": ["index.js"] +} diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/index.js b/node_modules/express/node_modules/connect/node_modules/bytes/index.js new file mode 100644 index 0000000..3eaafc7 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/index.js @@ -0,0 +1,39 @@ + +/** + * Parse byte `size` string. + * + * @param {String} size + * @return {Number} + * @api public + */ + +module.exports = function(size) { + if ('number' == typeof size) return convert(size); + var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/) + , n = parseFloat(parts[1]) + , type = parts[2]; + + var map = { + kb: 1 << 10 + , mb: 1 << 20 + , gb: 1 << 30 + }; + + return map[type] * n; +}; + +/** + * convert bytes into string. + * + * @param {Number} b - bytes to convert + * @return {String}i + * @api public + */ + +function convert (b) { + var gb = 1 << 30, mb = 1 << 20, kb = 1 << 10; + if (b >= gb) return (Math.round(b / gb * 100) / 100) + 'gb'; + if (b >= mb) return (Math.round(b / mb * 100) / 100) + 'mb'; + if (b >= kb) return (Math.round(b / kb * 100) / 100) + 'kb'; + return b; +} \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/bytes/package.json b/node_modules/express/node_modules/connect/node_modules/bytes/package.json new file mode 100644 index 0000000..05f17ec --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/bytes/package.json @@ -0,0 +1,24 @@ +{ + "name": "bytes", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "byte size string parser / serializer", + "version": "0.1.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "component": { + "scripts": { + "bytes": "index.js" + } + }, + "readme": "# node-bytes\n\n Byte string parser / formatter.\n\n## Example:\n\n```js\nbytes('1kb')\n// => 1024\n\nbytes('2mb')\n// => 2097152\n\nbytes('1gb')\n// => 1073741824\n\nbytes(1073741824)\n// => 1gb\n```\n\n## Installation\n\n```\n$ npm install bytes\n$ component install visionmedia/bytes.js\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "_id": "bytes@0.1.0", + "_from": "bytes@0.1.0" +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore new file mode 100644 index 0000000..4fbabb3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore @@ -0,0 +1,4 @@ +/test/tmp/ +*.upload +*.un~ +*.http diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/Makefile b/node_modules/express/node_modules/connect/node_modules/formidable/Makefile new file mode 100644 index 0000000..8945872 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/Makefile @@ -0,0 +1,14 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +build: npm test + +npm: + npm install . + +clean: + rm test/tmp/* + +.PHONY: test clean build diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md new file mode 100644 index 0000000..a5ca104 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md @@ -0,0 +1,311 @@ +# Formidable + +[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable) + +## Purpose + +A node.js module for parsing form data, especially file uploads. + +## Current status + +This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading +and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from +a large variety of clients and is considered production-ready. + +## Features + +* Fast (~500mb/sec), non-buffering multipart parser +* Automatically writing file uploads to disk +* Low memory footprint +* Graceful error handling +* Very high test coverage + +## Changelog + +### v1.0.9 + +* Emit progress when content length header parsed (Tim Koschützki) +* Fix Readme syntax due to GitHub changes (goob) +* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara) + +### v1.0.8 + +* Strip potentially unsafe characters when using `keepExtensions: true`. +* Switch to utest / urun for testing +* Add travis build + +### v1.0.7 + +* Remove file from package that was causing problems when installing on windows. (#102) +* Fix typos in Readme (Jason Davies). + +### v1.0.6 + +* Do not default to the default to the field name for file uploads where + filename="". + +### v1.0.5 + +* Support filename="" in multipart parts +* Explain unexpected end() errors in parser better + +**Note:** Starting with this version, formidable emits 'file' events for empty +file input fields. Previously those were incorrectly emitted as regular file +input fields with value = "". + +### v1.0.4 + +* Detect a good default tmp directory regardless of platform. (#88) + +### v1.0.3 + +* Fix problems with utf8 characters (#84) / semicolons in filenames (#58) +* Small performance improvements +* New test suite and fixture system + +### v1.0.2 + +* Exclude node\_modules folder from git +* Implement new `'aborted'` event +* Fix files in example folder to work with recent node versions +* Make gently a devDependency + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2) + +### v1.0.1 + +* Fix package.json to refer to proper main directory. (#68, Dean Landolt) + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1) + +### v1.0.0 + +* Add support for multipart boundaries that are quoted strings. (Jeff Craig) + +This marks the beginning of development on version 2.0 which will include +several architectural improvements. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0) + +### v0.9.11 + +* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki) +* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class + +**Important:** The old property names of the File class will be removed in a +future release. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11) + +### Older releases + +These releases were done before starting to maintain the above Changelog: + +* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10) +* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9) +* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8) +* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7) +* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6) +* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5) +* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4) +* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3) +* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2) +* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0) + +## Installation + +Via [npm](http://github.com/isaacs/npm): + + npm install formidable@latest + +Manually: + + git clone git://github.com/felixge/node-formidable.git formidable + vim my.js + # var formidable = require('./formidable'); + +Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library. + +## Example + +Parse an incoming file upload. + + var formidable = require('formidable'), + http = require('http'), + + util = require('util'); + + http.createServer(function(req, res) { + if (req.url == '/upload' && req.method.toLowerCase() == 'post') { + // parse a file upload + var form = new formidable.IncomingForm(); + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received upload:\n\n'); + res.end(util.inspect({fields: fields, files: files})); + }); + return; + } + + // show a file upload form + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + }).listen(80); + +## API + +### formidable.IncomingForm + +__new formidable.IncomingForm()__ + +Creates a new incoming form. + +__incomingForm.encoding = 'utf-8'__ + +The encoding to use for incoming form fields. + +__incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()__ + +The directory for placing file uploads in. You can move them later on using +`fs.rename()`. The default directory is picked at module load time depending on +the first existing directory from those listed above. + +__incomingForm.keepExtensions = false__ + +If you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`. + +__incomingForm.type__ + +Either 'multipart' or 'urlencoded' depending on the incoming request. + +__incomingForm.maxFieldsSize = 2 * 1024 * 1024__ + +Limits the amount of memory a field (not file) can allocate in bytes. +If this value is exceeded, an `'error'` event is emitted. The default +size is 2MB. + +__incomingForm.hash = false__ + +If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`. + +__incomingForm.bytesReceived__ + +The amount of bytes received for this form so far. + +__incomingForm.bytesExpected__ + +The expected number of bytes in this form. + +__incomingForm.parse(request, [cb])__ + +Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback: + + incomingForm.parse(req, function(err, fields, files) { + // ... + }); + +__incomingForm.onPart(part)__ + +You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing. + + incomingForm.onPart = function(part) { + part.addListener('data', function() { + // ... + }); + } + +If you want to use formidable to only handle certain parts for you, you can do so: + + incomingForm.onPart = function(part) { + if (!part.filename) { + // let formidable handle all non-file parts + incomingForm.handlePart(part); + } + } + +Check the code in this method for further inspiration. + +__Event: 'progress' (bytesReceived, bytesExpected)__ + +Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. + +__Event: 'field' (name, value)__ + +Emitted whenever a field / value pair has been received. + +__Event: 'fileBegin' (name, file)__ + +Emitted whenever a new file is detected in the upload stream. Use this even if +you want to stream the file to somewhere else while buffering the upload on +the file system. + +__Event: 'file' (name, file)__ + +Emitted whenever a field / file pair has been received. `file` is an instance of `File`. + +__Event: 'error' (err)__ + +Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events. + +__Event: 'aborted'__ + +Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core). + +__Event: 'end' ()__ + +Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response. + +### formidable.File + +__file.size = 0__ + +The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet. + +__file.path = null__ + +The path this file is being written to. You can modify this in the `'fileBegin'` event in +case you are unhappy with the way formidable generates a temporary path for your files. + +__file.name = null__ + +The name this file had according to the uploading client. + +__file.type = null__ + +The mime type of this file, according to the uploading client. + +__file.lastModifiedDate = null__ + +A date object (or `null`) containing the time this file was last written to. Mostly +here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). + +__file.hash = null__ + +If hash calculation was set, you can read the hex digest out of this var. + +## License + +Formidable is licensed under the MIT license. + +## Ports + +* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable + +## Credits + +* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/TODO b/node_modules/express/node_modules/connect/node_modules/formidable/TODO new file mode 100644 index 0000000..e1107f2 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/TODO @@ -0,0 +1,3 @@ +- Better bufferMaxSize handling approach +- Add tests for JSON parser pull request and merge it +- Implement QuerystringParser the same way as MultipartParser diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js new file mode 100644 index 0000000..bff41f1 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js @@ -0,0 +1,70 @@ +require('../test/common'); +var multipartParser = require('../lib/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + Buffer = require('buffer').Buffer, + boundary = '-----------------------------168072824752491622650073', + mb = 100, + buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), + callbacks = + { partBegin: -1, + partEnd: -1, + headerField: -1, + headerValue: -1, + partData: -1, + end: -1, + }; + + +parser.initWithBoundary(boundary); +parser.onHeaderField = function() { + callbacks.headerField++; +}; + +parser.onHeaderValue = function() { + callbacks.headerValue++; +}; + +parser.onPartBegin = function() { + callbacks.partBegin++; +}; + +parser.onPartData = function() { + callbacks.partData++; +}; + +parser.onPartEnd = function() { + callbacks.partEnd++; +}; + +parser.onEnd = function() { + callbacks.end++; +}; + +var start = +new Date(), + nparsed = parser.write(buffer), + duration = +new Date - start, + mbPerSec = (mb / (duration / 1000)).toFixed(2); + +console.log(mbPerSec+' mb/sec'); + +assert.equal(nparsed, buffer.length); + +function createMultipartBuffer(boundary, size) { + var head = + '--'+boundary+'\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + , tail = '\r\n--'+boundary+'--\r\n' + , buffer = new Buffer(size); + + buffer.write(head, 'ascii', 0); + buffer.write(tail, 'ascii', buffer.length - tail.length); + return buffer; +} + +process.on('exit', function() { + for (var k in callbacks) { + assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); + } +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js new file mode 100644 index 0000000..f6c15a6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js @@ -0,0 +1,43 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + } else if (req.url == '/post') { + var form = new formidable.IncomingForm(), + fields = []; + + form + .on('error', function(err) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('error:\n\n'+util.inspect(err)); + }) + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('end', function() { + console.log('-> post done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.end('received fields:\n\n '+util.inspect(fields)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js new file mode 100644 index 0000000..050cdd9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js @@ -0,0 +1,48 @@ +require('../test/common'); +var http = require('http'), + util = require('util'), + formidable = require('formidable'), + server; + +server = http.createServer(function(req, res) { + if (req.url == '/') { + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + } else if (req.url == '/upload') { + var form = new formidable.IncomingForm(), + files = [], + fields = []; + + form.uploadDir = TEST_TMP; + + form + .on('field', function(field, value) { + console.log(field, value); + fields.push([field, value]); + }) + .on('file', function(field, file) { + console.log(field, file); + files.push([field, file]); + }) + .on('end', function() { + console.log('-> upload done'); + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received fields:\n\n '+util.inspect(fields)); + res.write('\n\n'); + res.end('received files:\n\n '+util.inspect(files)); + }); + form.parse(req); + } else { + res.writeHead(404, {'content-type': 'text/plain'}); + res.end('404'); + } +}); +server.listen(TEST_PORT); + +console.log('listening on http://localhost:'+TEST_PORT+'/'); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/index.js new file mode 100644 index 0000000..be41032 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/formidable'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js new file mode 100644 index 0000000..dad8d5f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js @@ -0,0 +1,73 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var util = require('./util'), + WriteStream = require('fs').WriteStream, + EventEmitter = require('events').EventEmitter, + crypto = require('crypto'); + +function File(properties) { + EventEmitter.call(this); + + this.size = 0; + this.path = null; + this.name = null; + this.type = null; + this.hash = null; + this.lastModifiedDate = null; + + this._writeStream = null; + + for (var key in properties) { + this[key] = properties[key]; + } + + if(typeof this.hash === 'string') { + this.hash = crypto.createHash(properties.hash); + } + + this._backwardsCompatibility(); +} +module.exports = File; +util.inherits(File, EventEmitter); + +// @todo Next release: Show error messages when accessing these +File.prototype._backwardsCompatibility = function() { + var self = this; + this.__defineGetter__('length', function() { + return self.size; + }); + this.__defineGetter__('filename', function() { + return self.name; + }); + this.__defineGetter__('mime', function() { + return self.type; + }); +}; + +File.prototype.open = function() { + this._writeStream = new WriteStream(this.path); +}; + +File.prototype.write = function(buffer, cb) { + var self = this; + this._writeStream.write(buffer, function() { + if(self.hash) { + self.hash.update(buffer); + } + self.lastModifiedDate = new Date(); + self.size += buffer.length; + self.emit('progress', self.size); + cb(); + }); +}; + +File.prototype.end = function(cb) { + var self = this; + this._writeStream.end(function() { + if(self.hash) { + self.hash = self.hash.digest('hex'); + } + self.emit('end'); + cb(); + }); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js new file mode 100644 index 0000000..060eac2 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js @@ -0,0 +1,384 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var fs = require('fs'); +var util = require('./util'), + path = require('path'), + File = require('./file'), + MultipartParser = require('./multipart_parser').MultipartParser, + QuerystringParser = require('./querystring_parser').QuerystringParser, + StringDecoder = require('string_decoder').StringDecoder, + EventEmitter = require('events').EventEmitter, + Stream = require('stream').Stream; + +function IncomingForm(opts) { + if (!(this instanceof IncomingForm)) return new IncomingForm; + EventEmitter.call(this); + + opts=opts||{}; + + this.error = null; + this.ended = false; + + this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024; + this.keepExtensions = opts.keepExtensions || false; + this.uploadDir = opts.uploadDir || IncomingForm.UPLOAD_DIR; + this.encoding = opts.encoding || 'utf-8'; + this.headers = null; + this.type = null; + this.hash = false; + + this.bytesReceived = null; + this.bytesExpected = null; + + this._parser = null; + this._flushing = 0; + this._fieldsSize = 0; +}; +util.inherits(IncomingForm, EventEmitter); +exports.IncomingForm = IncomingForm; + +IncomingForm.UPLOAD_DIR = (function() { + var dirs = [process.env.TMP, '/tmp', process.cwd()]; + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var isDirectory = false; + + try { + isDirectory = fs.statSync(dir).isDirectory(); + } catch (e) {} + + if (isDirectory) return dir; + } +})(); + +IncomingForm.prototype.parse = function(req, cb) { + this.pause = function() { + try { + req.pause(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + return true; + }; + + this.resume = function() { + try { + req.resume(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + + return true; + }; + + this.writeHeaders(req.headers); + + var self = this; + req + .on('error', function(err) { + self._error(err); + }) + .on('aborted', function() { + self.emit('aborted'); + }) + .on('data', function(buffer) { + self.write(buffer); + }) + .on('end', function() { + if (self.error) { + return; + } + + var err = self._parser.end(); + if (err) { + self._error(err); + } + }); + + if (cb) { + var fields = {}, files = {}; + this + .on('field', function(name, value) { + fields[name] = value; + }) + .on('file', function(name, file) { + files[name] = file; + }) + .on('error', function(err) { + cb(err, fields, files); + }) + .on('end', function() { + cb(null, fields, files); + }); + } + + return this; +}; + +IncomingForm.prototype.writeHeaders = function(headers) { + this.headers = headers; + this._parseContentLength(); + this._parseContentType(); +}; + +IncomingForm.prototype.write = function(buffer) { + if (!this._parser) { + this._error(new Error('unintialized parser')); + return; + } + + this.bytesReceived += buffer.length; + this.emit('progress', this.bytesReceived, this.bytesExpected); + + var bytesParsed = this._parser.write(buffer); + if (bytesParsed !== buffer.length) { + this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); + } + + return bytesParsed; +}; + +IncomingForm.prototype.pause = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.resume = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.onPart = function(part) { + // this method can be overwritten by the user + this.handlePart(part); +}; + +IncomingForm.prototype.handlePart = function(part) { + var self = this; + + if (part.filename === undefined) { + var value = '' + , decoder = new StringDecoder(this.encoding); + + part.on('data', function(buffer) { + self._fieldsSize += buffer.length; + if (self._fieldsSize > self.maxFieldsSize) { + self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data')); + return; + } + value += decoder.write(buffer); + }); + + part.on('end', function() { + self.emit('field', part.name, value); + }); + return; + } + + this._flushing++; + + var file = new File({ + path: this._uploadPath(part.filename), + name: part.filename, + type: part.mime, + hash: self.hash + }); + + this.emit('fileBegin', part.name, file); + + file.open(); + + part.on('data', function(buffer) { + self.pause(); + file.write(buffer, function() { + self.resume(); + }); + }); + + part.on('end', function() { + file.end(function() { + self._flushing--; + self.emit('file', part.name, file); + self._maybeEnd(); + }); + }); +}; + +IncomingForm.prototype._parseContentType = function() { + if (!this.headers['content-type']) { + this._error(new Error('bad content-type header, no content-type')); + return; + } + + if (this.headers['content-type'].match(/urlencoded/i)) { + this._initUrlencoded(); + return; + } + + if (this.headers['content-type'].match(/multipart/i)) { + var m; + if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) { + this._initMultipart(m[1] || m[2]); + } else { + this._error(new Error('bad content-type header, no multipart boundary')); + } + return; + } + + this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); +}; + +IncomingForm.prototype._error = function(err) { + if (this.error) { + return; + } + + this.error = err; + this.pause(); + this.emit('error', err); +}; + +IncomingForm.prototype._parseContentLength = function() { + if (this.headers['content-length']) { + this.bytesReceived = 0; + this.bytesExpected = parseInt(this.headers['content-length'], 10); + this.emit('progress', this.bytesReceived, this.bytesExpected); + } +}; + +IncomingForm.prototype._newParser = function() { + return new MultipartParser(); +}; + +IncomingForm.prototype._initMultipart = function(boundary) { + this.type = 'multipart'; + + var parser = new MultipartParser(), + self = this, + headerField, + headerValue, + part; + + parser.initWithBoundary(boundary); + + parser.onPartBegin = function() { + part = new Stream(); + part.readable = true; + part.headers = {}; + part.name = null; + part.filename = null; + part.mime = null; + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString(self.encoding, start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString(self.encoding, start, end); + }; + + parser.onHeaderEnd = function() { + headerField = headerField.toLowerCase(); + part.headers[headerField] = headerValue; + + var m; + if (headerField == 'content-disposition') { + if (m = headerValue.match(/name="([^"]+)"/i)) { + part.name = m[1]; + } + + part.filename = self._fileName(headerValue); + } else if (headerField == 'content-type') { + part.mime = headerValue; + } + + headerField = ''; + headerValue = ''; + }; + + parser.onHeadersEnd = function() { + self.onPart(part); + }; + + parser.onPartData = function(b, start, end) { + part.emit('data', b.slice(start, end)); + }; + + parser.onPartEnd = function() { + part.emit('end'); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._fileName = function(headerValue) { + var m = headerValue.match(/filename="(.*?)"($|; )/i) + if (!m) return; + + var filename = m[1].substr(m[1].lastIndexOf('\\') + 1); + filename = filename.replace(/%22/g, '"'); + filename = filename.replace(/&#([\d]{4});/g, function(m, code) { + return String.fromCharCode(code); + }); + return filename; +}; + +IncomingForm.prototype._initUrlencoded = function() { + this.type = 'urlencoded'; + + var parser = new QuerystringParser() + , self = this; + + parser.onField = function(key, val) { + self.emit('field', key, val); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._uploadPath = function(filename) { + var name = ''; + for (var i = 0; i < 32; i++) { + name += Math.floor(Math.random() * 16).toString(16); + } + + if (this.keepExtensions) { + var ext = path.extname(filename); + ext = ext.replace(/(\.[a-z0-9]+).*/, '$1') + + name += ext; + } + + return path.join(this.uploadDir, name); +}; + +IncomingForm.prototype._maybeEnd = function() { + if (!this.ended || this._flushing) { + return; + } + + this.emit('end'); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js new file mode 100644 index 0000000..7a6e3e1 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js @@ -0,0 +1,3 @@ +var IncomingForm = require('./incoming_form').IncomingForm; +IncomingForm.IncomingForm = IncomingForm; +module.exports = IncomingForm; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js new file mode 100644 index 0000000..9ca567c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js @@ -0,0 +1,312 @@ +var Buffer = require('buffer').Buffer, + s = 0, + S = + { PARSER_UNINITIALIZED: s++, + START: s++, + START_BOUNDARY: s++, + HEADER_FIELD_START: s++, + HEADER_FIELD: s++, + HEADER_VALUE_START: s++, + HEADER_VALUE: s++, + HEADER_VALUE_ALMOST_DONE: s++, + HEADERS_ALMOST_DONE: s++, + PART_DATA_START: s++, + PART_DATA: s++, + PART_END: s++, + END: s++, + }, + + f = 1, + F = + { PART_BOUNDARY: f, + LAST_BOUNDARY: f *= 2, + }, + + LF = 10, + CR = 13, + SPACE = 32, + HYPHEN = 45, + COLON = 58, + A = 97, + Z = 122, + + lower = function(c) { + return c | 0x20; + }; + +for (var s in S) { + exports[s] = S[s]; +} + +function MultipartParser() { + this.boundary = null; + this.boundaryChars = null; + this.lookbehind = null; + this.state = S.PARSER_UNINITIALIZED; + + this.index = null; + this.flags = 0; +}; +exports.MultipartParser = MultipartParser; + +MultipartParser.stateToString = function(stateNumber) { + for (var state in S) { + var number = S[state]; + if (number === stateNumber) return state; + } +}; + +MultipartParser.prototype.initWithBoundary = function(str) { + this.boundary = new Buffer(str.length+4); + this.boundary.write('\r\n--', 'ascii', 0); + this.boundary.write(str, 'ascii', 4); + this.lookbehind = new Buffer(this.boundary.length+8); + this.state = S.START; + + this.boundaryChars = {}; + for (var i = 0; i < this.boundary.length; i++) { + this.boundaryChars[this.boundary[i]] = true; + } +}; + +MultipartParser.prototype.write = function(buffer) { + var self = this, + i = 0, + len = buffer.length, + prevIndex = this.index, + index = this.index, + state = this.state, + flags = this.flags, + lookbehind = this.lookbehind, + boundary = this.boundary, + boundaryChars = this.boundaryChars, + boundaryLength = this.boundary.length, + boundaryEnd = boundaryLength - 1, + bufferLength = buffer.length, + c, + cl, + + mark = function(name) { + self[name+'Mark'] = i; + }, + clear = function(name) { + delete self[name+'Mark']; + }, + callback = function(name, buffer, start, end) { + if (start !== undefined && start === end) { + return; + } + + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](buffer, start, end); + } + }, + dataCallback = function(name, clear) { + var markSymbol = name+'Mark'; + if (!(markSymbol in self)) { + return; + } + + if (!clear) { + callback(name, buffer, self[markSymbol], buffer.length); + self[markSymbol] = 0; + } else { + callback(name, buffer, self[markSymbol], i); + delete self[markSymbol]; + } + }; + + for (i = 0; i < len; i++) { + c = buffer[i]; + switch (state) { + case S.PARSER_UNINITIALIZED: + return i; + case S.START: + index = 0; + state = S.START_BOUNDARY; + case S.START_BOUNDARY: + if (index == boundary.length - 2) { + if (c != CR) { + return i; + } + index++; + break; + } else if (index - 1 == boundary.length - 2) { + if (c != LF) { + return i; + } + index = 0; + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + + if (c != boundary[index+2]) { + return i; + } + index++; + break; + case S.HEADER_FIELD_START: + state = S.HEADER_FIELD; + mark('headerField'); + index = 0; + case S.HEADER_FIELD: + if (c == CR) { + clear('headerField'); + state = S.HEADERS_ALMOST_DONE; + break; + } + + index++; + if (c == HYPHEN) { + break; + } + + if (c == COLON) { + if (index == 1) { + // empty header field + return i; + } + dataCallback('headerField', true); + state = S.HEADER_VALUE_START; + break; + } + + cl = lower(c); + if (cl < A || cl > Z) { + return i; + } + break; + case S.HEADER_VALUE_START: + if (c == SPACE) { + break; + } + + mark('headerValue'); + state = S.HEADER_VALUE; + case S.HEADER_VALUE: + if (c == CR) { + dataCallback('headerValue', true); + callback('headerEnd'); + state = S.HEADER_VALUE_ALMOST_DONE; + } + break; + case S.HEADER_VALUE_ALMOST_DONE: + if (c != LF) { + return i; + } + state = S.HEADER_FIELD_START; + break; + case S.HEADERS_ALMOST_DONE: + if (c != LF) { + return i; + } + + callback('headersEnd'); + state = S.PART_DATA_START; + break; + case S.PART_DATA_START: + state = S.PART_DATA + mark('partData'); + case S.PART_DATA: + prevIndex = index; + + if (index == 0) { + // boyer-moore derrived algorithm to safely skip non-boundary data + i += boundaryEnd; + while (i < bufferLength && !(buffer[i] in boundaryChars)) { + i += boundaryLength; + } + i -= boundaryEnd; + c = buffer[i]; + } + + if (index < boundary.length) { + if (boundary[index] == c) { + if (index == 0) { + dataCallback('partData', true); + } + index++; + } else { + index = 0; + } + } else if (index == boundary.length) { + index++; + if (c == CR) { + // CR = part boundary + flags |= F.PART_BOUNDARY; + } else if (c == HYPHEN) { + // HYPHEN = end boundary + flags |= F.LAST_BOUNDARY; + } else { + index = 0; + } + } else if (index - 1 == boundary.length) { + if (flags & F.PART_BOUNDARY) { + index = 0; + if (c == LF) { + // unset the PART_BOUNDARY flag + flags &= ~F.PART_BOUNDARY; + callback('partEnd'); + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + } else if (flags & F.LAST_BOUNDARY) { + if (c == HYPHEN) { + callback('partEnd'); + callback('end'); + state = S.END; + } else { + index = 0; + } + } else { + index = 0; + } + } + + if (index > 0) { + // when matching a possible boundary, keep a lookbehind reference + // in case it turns out to be a false lead + lookbehind[index-1] = c; + } else if (prevIndex > 0) { + // if our boundary turned out to be rubbish, the captured lookbehind + // belongs to partData + callback('partData', lookbehind, 0, prevIndex); + prevIndex = 0; + mark('partData'); + + // reconsider the current character even so it interrupted the sequence + // it could be the beginning of a new sequence + i--; + } + + break; + case S.END: + break; + default: + return i; + } + } + + dataCallback('headerField'); + dataCallback('headerValue'); + dataCallback('partData'); + + this.index = index; + this.state = state; + this.flags = flags; + + return len; +}; + +MultipartParser.prototype.end = function() { + if (this.state != S.END) { + return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain()); + } +}; + +MultipartParser.prototype.explain = function() { + return 'state = ' + MultipartParser.stateToString(this.state); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js new file mode 100644 index 0000000..63f109e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js @@ -0,0 +1,25 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +// This is a buffering parser, not quite as nice as the multipart one. +// If I find time I'll rewrite this to be fully streaming as well +var querystring = require('querystring'); + +function QuerystringParser() { + this.buffer = ''; +}; +exports.QuerystringParser = QuerystringParser; + +QuerystringParser.prototype.write = function(buffer) { + this.buffer += buffer.toString('ascii'); + return buffer.length; +}; + +QuerystringParser.prototype.end = function() { + var fields = querystring.parse(this.buffer); + for (var field in fields) { + this.onField(field, fields[field]); + } + this.buffer = ''; + + this.onEnd(); +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js new file mode 100644 index 0000000..e9493e9 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js @@ -0,0 +1,6 @@ +// Backwards compatibility ... +try { + module.exports = require('util'); +} catch (e) { + module.exports = require('sys'); +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/Makefile b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/Makefile new file mode 100644 index 0000000..01f7140 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/Makefile @@ -0,0 +1,4 @@ +test: + @find test/simple/test-*.js | xargs -n 1 -t node + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/Readme.md b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/Readme.md new file mode 100644 index 0000000..f8f0c66 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/Readme.md @@ -0,0 +1,167 @@ +# Gently + +## Purpose + +A node.js module that helps with stubbing and behavior verification. It allows you to test the most remote and nested corners of your code while keeping being fully unobtrusive. + +## Features + +* Overwrite and stub individual object functions +* Verify that all expected calls have been made in the expected order +* Restore stubbed functions to their original behavior +* Detect object / class names from obj.constructor.name and obj.toString() +* Hijack any required module function or class constructor + +## Installation + +Via [npm](http://github.com/isaacs/npm): + + npm install gently@latest + +## Example + +Make sure your dog is working properly: + + function Dog() {} + + Dog.prototype.seeCat = function() { + this.bark('whuf, whuf'); + this.run(); + } + + Dog.prototype.bark = function(bark) { + require('sys').puts(bark); + } + + var gently = new (require('gently')) + , assert = require('assert') + , dog = new Dog(); + + gently.expect(dog, 'bark', function(bark) { + assert.equal(bark, 'whuf, whuf'); + }); + gently.expect(dog, 'run'); + + dog.seeCat(); + +You can also easily test event emitters with this, for example a simple sequence of 2 events emitted by `fs.WriteStream`: + + var gently = new (require('gently')) + , stream = new (require('fs').WriteStream)('my_file.txt'); + + gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'open'); + }); + + gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'drain'); + }); + +For a full read world example, check out this test case: [test-incoming-form.js](http://github.com/felixge/node-formidable/blob/master/test/simple/test-incoming-form.js) (in [node-formdiable](http://github.com/felixge/node-formidable)). + +## API + +### Gently + +#### new Gently() + +Creates a new gently instance. It listens to the process `'exit'` event to make sure all expectations have been verified. + +#### gently.expect(obj, method, [[count], stubFn]) + +Creates an expectation for an objects method to be called. You can optionally specify the call `count` you are expecting, as well as `stubFn` function that will run instead of the original function. + +Returns a reference to the function that is getting overwritten. + +#### gently.expect([count], stubFn) + +Returns a function that is supposed to be executed `count` times, delegating any calls to the provided `stubFn` function. Naming your stubFn closure will help to properly diagnose errors that are being thrown: + + childProcess.exec('ls', gently.expect(function lsCallback(code) { + assert.equal(0, code); + })); + +#### gently.restore(obj, method) + +Restores an object method that has been previously overwritten using `gently.expect()`. + +#### gently.hijack(realRequire) + +Returns a new require functions that catches a reference to all required modules into `gently.hijacked`. + +To use this function, include a line like this in your `'my-module.js'`. + + if (global.GENTLY) require = GENTLY.hijack(require); + + var sys = require('sys'); + exports.hello = function() { + sys.log('world'); + }; + +Now you can write a test for the module above: + + var gently = global.GENTLY = new (require('gently')) + , myModule = require('./my-module'); + + gently.expect(gently.hijacked.sys, 'log', function(str) { + assert.equal(str, 'world'); + }); + + myModule.hello(); + +#### gently.stub(location, [exportsName]) + +Returns a stub class that will be used instead of the real class from the module at `location` with the given `exportsName`. + +This allows to test an OOP version of the previous example, where `'my-module.js'`. + + if (global.GENTLY) require = GENTLY.hijack(require); + + var World = require('./world'); + + exports.hello = function() { + var world = new World(); + world.hello(); + } + +And `world.js` looks like this: + + var sys = require('sys'); + + function World() { + + } + module.exports = World; + + World.prototype.hello = function() { + sys.log('world'); + }; + +Testing `'my-module.js'` can now easily be accomplished: + + var gently = global.GENTLY = new (require('gently')) + , WorldStub = gently.stub('./world') + , myModule = require('./my-module') + , WORLD; + + gently.expect(WorldStub, 'new', function() { + WORLD = this; + }); + + gently.expect(WORLD, 'hello'); + + myModule.hello(); + +#### gently.hijacked + +An object that holds the references to all hijacked modules. + +#### gently.verify([msg]) + +Verifies that all expectations of this gently instance have been satisfied. If not called manually, this method is called when the process `'exit'` event is fired. + +If `msg` is given, it will appear in any error that might be thrown. + +## License + +Gently is licensed under the MIT license. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/example/dog.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/example/dog.js new file mode 100644 index 0000000..022fae0 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/example/dog.js @@ -0,0 +1,22 @@ +require('../test/common'); +function Dog() {} + +Dog.prototype.seeCat = function() { + this.bark('whuf, whuf'); + this.run(); +} + +Dog.prototype.bark = function(bark) { + require('sys').puts(bark); +} + +var gently = new (require('gently')) + , assert = require('assert') + , dog = new Dog(); + +gently.expect(dog, 'bark', function(bark) { + assert.equal(bark, 'whuf, whuf'); +}); +gently.expect(dog, 'run'); + +dog.seeCat(); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/example/event_emitter.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/example/event_emitter.js new file mode 100644 index 0000000..7def134 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/example/event_emitter.js @@ -0,0 +1,11 @@ +require('../test/common'); +var gently = new (require('gently')) + , stream = new (require('fs').WriteStream)('my_file.txt'); + +gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'open'); +}); + +gently.expect(stream, 'emit', function(event) { + assert.equal(event, 'drain'); +}); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/index.js new file mode 100644 index 0000000..69122bd --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/gently'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/lib/gently/gently.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/lib/gently/gently.js new file mode 100644 index 0000000..8af0e1e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/lib/gently/gently.js @@ -0,0 +1,184 @@ +var path = require('path'); + +function Gently() { + this.expectations = []; + this.hijacked = {}; + + var self = this; + process.addListener('exit', function() { + self.verify('process exit'); + }); +}; +module.exports = Gently; + +Gently.prototype.stub = function(location, exportsName) { + function Stub() { + return Stub['new'].apply(this, arguments); + }; + + Stub['new'] = function () {}; + + var stubName = 'require('+JSON.stringify(location)+')'; + if (exportsName) { + stubName += '.'+exportsName; + } + + Stub.prototype.toString = Stub.toString = function() { + return stubName; + }; + + var exports = this.hijacked[location] || {}; + if (exportsName) { + exports[exportsName] = Stub; + } else { + exports = Stub; + } + + this.hijacked[location] = exports; + return Stub; +}; + +Gently.prototype.hijack = function(realRequire) { + var self = this; + return function(location) { + return self.hijacked[location] = (self.hijacked[location]) + ? self.hijacked[location] + : realRequire(location); + }; +}; + +Gently.prototype.expect = function(obj, method, count, stubFn) { + if (typeof obj != 'function' && typeof obj != 'object' && typeof obj != 'number') { + throw new Error + ( 'Bad 1st argument for gently.expect(), ' + + 'object, function, or number expected, got: '+(typeof obj) + ); + } else if (typeof obj == 'function' && (typeof method != 'string')) { + // expect(stubFn) interface + stubFn = obj; + obj = null; + method = null; + count = 1; + } else if (typeof method == 'function') { + // expect(count, stubFn) interface + count = obj; + stubFn = method; + obj = null; + method = null; + } else if (typeof count == 'function') { + // expect(obj, method, stubFn) interface + stubFn = count; + count = 1; + } else if (count === undefined) { + // expect(obj, method) interface + count = 1; + } + + var name = this._name(obj, method, stubFn); + this.expectations.push({obj: obj, method: method, stubFn: stubFn, name: name, count: count}); + + var self = this; + function delegate() { + return self._stubFn(this, obj, method, name, Array.prototype.slice.call(arguments)); + } + + if (!obj) { + return delegate; + } + + var original = (obj[method]) + ? obj[method]._original || obj[method] + : undefined; + + obj[method] = delegate; + return obj[method]._original = original; +}; + +Gently.prototype.restore = function(obj, method) { + if (!obj[method] || !obj[method]._original) { + throw new Error(this._name(obj, method)+' is not gently stubbed'); + } + obj[method] = obj[method]._original; +}; + +Gently.prototype.verify = function(msg) { + if (!this.expectations.length) { + return; + } + + var validExpectations = []; + for (var i = 0, l = this.expectations.length; i < l; i++) { + var expectation = this.expectations[i]; + + if (expectation.count > 0) { + validExpectations.push(expectation); + } + } + + this.expectations = []; // reset so that no duplicate verification attempts are made + + if (!validExpectations.length) { + return; + } + + var expectation = validExpectations[0]; + + throw new Error + ( 'Expected call to '+expectation.name+' did not happen' + + ( (msg) + ? ' ('+msg+')' + : '' + ) + ); +}; + +Gently.prototype._stubFn = function(self, obj, method, name, args) { + var expectation = this.expectations[0], obj, method; + + if (!expectation) { + throw new Error('Unexpected call to '+name+', no call was expected'); + } + + if (expectation.obj !== obj || expectation.method !== method) { + throw new Error('Unexpected call to '+name+', expected call to '+ expectation.name); + } + + expectation.count -= 1; + if (expectation.count === 0) { + this.expectations.shift(); + + // autorestore original if its not a closure + // and no more expectations on that object + var has_more_expectations = this.expectations.reduce(function (memo, expectation) { + return memo || (expectation.obj === obj && expectation.method === method); + }, false); + if (obj !== null && method !== null && !has_more_expectations) { + if (typeof obj[method]._original !== 'undefined') { + obj[method] = obj[method]._original; + delete obj[method]._original; + } else { + delete obj[method]; + } + } + } + + if (expectation.stubFn) { + return expectation.stubFn.apply(self, args); + } +}; + +Gently.prototype._name = function(obj, method, stubFn) { + if (obj) { + var objectName = obj.toString(); + if (objectName == '[object Object]' && obj.constructor.name) { + objectName = '['+obj.constructor.name+']'; + } + return (objectName)+'.'+method+'()'; + } + + if (stubFn.name) { + return stubFn.name+'()'; + } + + return '>> '+stubFn.toString()+' <<'; +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/lib/gently/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/lib/gently/index.js new file mode 100644 index 0000000..64c1977 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/lib/gently/index.js @@ -0,0 +1 @@ +module.exports = require('./gently'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/package.json b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/package.json new file mode 100644 index 0000000..9c1b7a0 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/package.json @@ -0,0 +1,14 @@ +{ + "name": "gently", + "version": "0.9.2", + "directories": { + "lib": "./lib/gently" + }, + "main": "./lib/gently/index", + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": "*" + }, + "optionalDependencies": {} +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/test/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/test/common.js new file mode 100644 index 0000000..978b5c5 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/test/common.js @@ -0,0 +1,8 @@ +var path = require('path') + , sys = require('sys'); + +require.paths.unshift(path.dirname(__dirname)+'/lib'); + +global.puts = sys.puts; +global.p = function() {sys.error(sys.inspect.apply(null, arguments))};; +global.assert = require('assert'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/test/simple/test-gently.js b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/test/simple/test-gently.js new file mode 100644 index 0000000..4f8fe2d --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/node-gently/test/simple/test-gently.js @@ -0,0 +1,348 @@ +require('../common'); +var Gently = require('gently') + , gently; + +function test(test) { + process.removeAllListeners('exit'); + gently = new Gently(); + test(); +} + +test(function constructor() { + assert.deepEqual(gently.expectations, []); + assert.deepEqual(gently.hijacked, {}); + assert.equal(gently.constructor.name, 'Gently'); +}); + +test(function expectBadArgs() { + var BAD_ARG = 'oh no'; + try { + gently.expect(BAD_ARG); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Bad 1st argument for gently.expect(), object, function, or number expected, got: '+(typeof BAD_ARG)); + } +}); + +test(function expectObjMethod() { + var OBJ = {}, NAME = 'foobar'; + OBJ.foo = function(x) { + return x; + }; + + gently._name = function() { + return NAME; + }; + + var original = OBJ.foo + , stubFn = function() {}; + + (function testAddOne() { + assert.strictEqual(gently.expect(OBJ, 'foo', stubFn), original); + + assert.equal(gently.expectations.length, 1); + var expectation = gently.expectations[0]; + assert.strictEqual(expectation.obj, OBJ); + assert.strictEqual(expectation.method, 'foo'); + assert.strictEqual(expectation.stubFn, stubFn); + assert.strictEqual(expectation.name, NAME); + assert.strictEqual(OBJ.foo._original, original); + })(); + + (function testAddTwo() { + gently.expect(OBJ, 'foo', 2, stubFn); + assert.equal(gently.expectations.length, 2); + assert.strictEqual(OBJ.foo._original, original); + })(); + + (function testAddOneWithoutMock() { + gently.expect(OBJ, 'foo'); + assert.equal(gently.expectations.length, 3); + })(); + + var stubFnCalled = 0, SELF = {}; + gently._stubFn = function(self, obj, method, name, args) { + stubFnCalled++; + assert.strictEqual(self, SELF); + assert.strictEqual(obj, OBJ); + assert.strictEqual(method, 'foo'); + assert.strictEqual(name, NAME); + assert.deepEqual(args, [1, 2]); + return 23; + }; + assert.equal(OBJ.foo.apply(SELF, [1, 2]), 23); + assert.equal(stubFnCalled, 1); +}); + +test(function expectClosure() { + var NAME = 'MY CLOSURE'; + function closureFn() {}; + + gently._name = function() { + return NAME; + }; + + var fn = gently.expect(closureFn); + assert.equal(gently.expectations.length, 1); + var expectation = gently.expectations[0]; + assert.strictEqual(expectation.obj, null); + assert.strictEqual(expectation.method, null); + assert.strictEqual(expectation.stubFn, closureFn); + assert.strictEqual(expectation.name, NAME); + + var stubFnCalled = 0, SELF = {}; + gently._stubFn = function(self, obj, method, name, args) { + stubFnCalled++; + assert.strictEqual(self, SELF); + assert.strictEqual(obj, null); + assert.strictEqual(method, null); + assert.strictEqual(name, NAME); + assert.deepEqual(args, [1, 2]); + return 23; + }; + assert.equal(fn.apply(SELF, [1, 2]), 23); + assert.equal(stubFnCalled, 1); +}); + +test(function expectClosureCount() { + var stubFnCalled = 0; + function closureFn() {stubFnCalled++}; + + var fn = gently.expect(2, closureFn); + assert.equal(gently.expectations.length, 1); + fn(); + assert.equal(gently.expectations.length, 1); + fn(); + assert.equal(stubFnCalled, 2); +}); + +test(function restore() { + var OBJ = {}, NAME = '[my object].myFn()'; + OBJ.foo = function(x) { + return x; + }; + + gently._name = function() { + return NAME; + }; + + var original = OBJ.foo; + gently.expect(OBJ, 'foo'); + gently.restore(OBJ, 'foo'); + assert.strictEqual(OBJ.foo, original); + + (function testError() { + try { + gently.restore(OBJ, 'foo'); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, NAME+' is not gently stubbed'); + } + })(); +}); + +test(function _stubFn() { + var OBJ1 = {toString: function() {return '[OBJ 1]'}} + , OBJ2 = {toString: function() {return '[OBJ 2]'}, foo: function () {return 'bar';}} + , SELF = {}; + + gently.expect(OBJ1, 'foo', function(x) { + assert.strictEqual(this, SELF); + return x * 2; + }); + + assert.equal(gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]), 10); + + (function testAutorestore() { + assert.equal(OBJ2.foo(), 'bar'); + + gently.expect(OBJ2, 'foo', function() { + return 'stubbed foo'; + }); + + gently.expect(OBJ2, 'foo', function() { + return "didn't restore yet"; + }); + + assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), 'stubbed foo'); + assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), "didn't restore yet"); + assert.equal(OBJ2.foo(), 'bar'); + assert.deepEqual(gently.expectations, []); + })(); + + (function testNoMoreCallExpected() { + try { + gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Unexpected call to dummy_name, no call was expected'); + } + })(); + + (function testDifferentCallExpected() { + gently.expect(OBJ2, 'bar'); + try { + gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Unexpected call to dummy_name, expected call to '+gently._name(OBJ2, 'bar')); + } + + assert.equal(gently.expectations.length, 1); + })(); + + (function testNoMockCallback() { + OBJ2.bar(); + assert.equal(gently.expectations.length, 0); + })(); +}); + +test(function stub() { + var LOCATION = './my_class'; + + (function testRegular() { + var Stub = gently.stub(LOCATION); + assert.ok(Stub instanceof Function); + assert.strictEqual(gently.hijacked[LOCATION], Stub); + assert.ok(Stub['new'] instanceof Function); + assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+')'); + + (function testConstructor() { + var newCalled = 0 + , STUB + , ARGS = ['foo', 'bar']; + + Stub['new'] = function(a, b) { + assert.equal(a, ARGS[0]); + assert.equal(b, ARGS[1]); + newCalled++; + STUB = this; + }; + + var stub = new Stub(ARGS[0], ARGS[1]); + assert.strictEqual(stub, STUB); + assert.equal(newCalled, 1); + assert.equal(stub.toString(), 'require('+JSON.stringify(LOCATION)+')'); + })(); + + (function testUseReturnValueAsInstance() { + var R = {}; + + Stub['new'] = function() { + return R; + }; + + var stub = new Stub(); + assert.strictEqual(stub, R); + + })(); + })(); + + var EXPORTS_NAME = 'MyClass'; + test(function testExportsName() { + var Stub = gently.stub(LOCATION, EXPORTS_NAME); + assert.strictEqual(gently.hijacked[LOCATION][EXPORTS_NAME], Stub); + assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME); + + (function testConstructor() { + var stub = new Stub(); + assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME); + })(); + }); +}); + +test(function hijack() { + var LOCATION = './foo' + , REQUIRE_CALLS = 0 + , EXPORTS = {} + , REQUIRE = function() { + REQUIRE_CALLS++; + return EXPORTS; + }; + + var hijackedRequire = gently.hijack(REQUIRE); + hijackedRequire(LOCATION); + assert.strictEqual(gently.hijacked[LOCATION], EXPORTS); + + assert.equal(REQUIRE_CALLS, 1); + + // make sure we are caching the hijacked module + hijackedRequire(LOCATION); + assert.equal(REQUIRE_CALLS, 1); +}); + +test(function verify() { + var OBJ = {toString: function() {return '[OBJ]'}}; + gently.verify(); + + gently.expect(OBJ, 'foo'); + try { + gently.verify(); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen'); + } + + try { + gently.verify('foo'); + assert.ok(false, 'throw needs to happen'); + } catch (e) { + assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen (foo)'); + } +}); + +test(function processExit() { + var verifyCalled = 0; + gently.verify = function(msg) { + verifyCalled++; + assert.equal(msg, 'process exit'); + }; + + process.emit('exit'); + assert.equal(verifyCalled, 1); +}); + +test(function _name() { + (function testNamedClass() { + function Foo() {}; + var foo = new Foo(); + assert.equal(gently._name(foo, 'bar'), '[Foo].bar()'); + })(); + + (function testToStringPreference() { + function Foo() {}; + Foo.prototype.toString = function() { + return '[Superman 123]'; + }; + var foo = new Foo(); + assert.equal(gently._name(foo, 'bar'), '[Superman 123].bar()'); + })(); + + (function testUnamedClass() { + var Foo = function() {}; + var foo = new Foo(); + assert.equal(gently._name(foo, 'bar'), foo.toString()+'.bar()'); + })(); + + (function testNamedClosure() { + function myClosure() {}; + assert.equal(gently._name(null, null, myClosure), myClosure.name+'()'); + })(); + + (function testUnamedClosure() { + var myClosure = function() {2+2 == 5}; + assert.equal(gently._name(null, null, myClosure), '>> '+myClosure.toString()+' <<'); + })(); +}); + +test(function verifyExpectNone() { + var OBJ = {toString: function() {return '[OBJ]'}}; + gently.verify(); + + gently.expect(OBJ, 'foo', 0); + try { + gently.verify(); + } catch (e) { + assert.fail('Exception should not have been thrown'); + } +}); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/package.json b/node_modules/express/node_modules/connect/node_modules/formidable/package.json new file mode 100644 index 0000000..6d368f3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/package.json @@ -0,0 +1,27 @@ +{ + "name": "formidable", + "version": "1.0.11", + "dependencies": {}, + "devDependencies": { + "gently": "0.8.0", + "findit": "0.1.1", + "hashish": "0.0.4", + "urun": "0.0.4", + "utest": "0.0.3" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/index", + "scripts": { + "test": "make test" + }, + "engines": { + "node": "*" + }, + "optionalDependencies": {}, + "readme": "# Formidable\n\n[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)\n\n## Purpose\n\nA node.js module for parsing form data, especially file uploads.\n\n## Current status\n\nThis module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading\nand encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from\na large variety of clients and is considered production-ready.\n\n## Features\n\n* Fast (~500mb/sec), non-buffering multipart parser\n* Automatically writing file uploads to disk\n* Low memory footprint\n* Graceful error handling\n* Very high test coverage\n\n## Changelog\n\n### v1.0.9\n\n* Emit progress when content length header parsed (Tim Koschützki)\n* Fix Readme syntax due to GitHub changes (goob)\n* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)\n\n### v1.0.8\n\n* Strip potentially unsafe characters when using `keepExtensions: true`.\n* Switch to utest / urun for testing\n* Add travis build\n\n### v1.0.7\n\n* Remove file from package that was causing problems when installing on windows. (#102)\n* Fix typos in Readme (Jason Davies).\n\n### v1.0.6\n\n* Do not default to the default to the field name for file uploads where\n filename=\"\".\n\n### v1.0.5\n\n* Support filename=\"\" in multipart parts\n* Explain unexpected end() errors in parser better\n\n**Note:** Starting with this version, formidable emits 'file' events for empty\nfile input fields. Previously those were incorrectly emitted as regular file\ninput fields with value = \"\".\n\n### v1.0.4\n\n* Detect a good default tmp directory regardless of platform. (#88)\n\n### v1.0.3\n\n* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)\n* Small performance improvements\n* New test suite and fixture system\n\n### v1.0.2\n\n* Exclude node\\_modules folder from git\n* Implement new `'aborted'` event\n* Fix files in example folder to work with recent node versions\n* Make gently a devDependency\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)\n\n### v1.0.1\n\n* Fix package.json to refer to proper main directory. (#68, Dean Landolt)\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)\n\n### v1.0.0\n\n* Add support for multipart boundaries that are quoted strings. (Jeff Craig)\n\nThis marks the beginning of development on version 2.0 which will include\nseveral architectural improvements.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)\n\n### v0.9.11\n\n* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)\n* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class\n\n**Important:** The old property names of the File class will be removed in a\nfuture release.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)\n\n### Older releases\n\nThese releases were done before starting to maintain the above Changelog:\n\n* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)\n* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)\n* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)\n* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)\n* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)\n* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)\n* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)\n* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)\n* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)\n* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)\n\n## Installation\n\nVia [npm](http://github.com/isaacs/npm):\n\n npm install formidable@latest\n\nManually:\n\n git clone git://github.com/felixge/node-formidable.git formidable\n vim my.js\n # var formidable = require('./formidable');\n\nNote: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.\n\n## Example\n\nParse an incoming file upload.\n\n var formidable = require('formidable'),\n http = require('http'),\n\n util = require('util');\n\n http.createServer(function(req, res) {\n if (req.url == '/upload' && req.method.toLowerCase() == 'post') {\n // parse a file upload\n var form = new formidable.IncomingForm();\n form.parse(req, function(err, fields, files) {\n res.writeHead(200, {'content-type': 'text/plain'});\n res.write('received upload:\\n\\n');\n res.end(util.inspect({fields: fields, files: files}));\n });\n return;\n }\n\n // show a file upload form\n res.writeHead(200, {'content-type': 'text/html'});\n res.end(\n '
    '+\n '
    '+\n '
    '+\n ''+\n '
    '\n );\n }).listen(80);\n\n## API\n\n### formidable.IncomingForm\n\n__new formidable.IncomingForm()__\n\nCreates a new incoming form.\n\n__incomingForm.encoding = 'utf-8'__\n\nThe encoding to use for incoming form fields.\n\n__incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()__\n\nThe directory for placing file uploads in. You can move them later on using\n`fs.rename()`. The default directory is picked at module load time depending on\nthe first existing directory from those listed above.\n\n__incomingForm.keepExtensions = false__\n\nIf you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`.\n\n__incomingForm.type__\n\nEither 'multipart' or 'urlencoded' depending on the incoming request.\n\n__incomingForm.maxFieldsSize = 2 * 1024 * 1024__\n\nLimits the amount of memory a field (not file) can allocate in bytes.\nIf this value is exceeded, an `'error'` event is emitted. The default\nsize is 2MB.\n\n__incomingForm.hash = false__\n\nIf you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.\n\n__incomingForm.bytesReceived__\n\nThe amount of bytes received for this form so far.\n\n__incomingForm.bytesExpected__\n\nThe expected number of bytes in this form.\n\n__incomingForm.parse(request, [cb])__\n\nParses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:\n\n incomingForm.parse(req, function(err, fields, files) {\n // ...\n });\n\n__incomingForm.onPart(part)__\n\nYou may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.\n\n incomingForm.onPart = function(part) {\n part.addListener('data', function() {\n // ...\n });\n }\n\nIf you want to use formidable to only handle certain parts for you, you can do so:\n\n incomingForm.onPart = function(part) {\n if (!part.filename) {\n // let formidable handle all non-file parts\n incomingForm.handlePart(part);\n }\n }\n\nCheck the code in this method for further inspiration.\n\n__Event: 'progress' (bytesReceived, bytesExpected)__\n\nEmitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.\n\n__Event: 'field' (name, value)__\n\nEmitted whenever a field / value pair has been received.\n\n__Event: 'fileBegin' (name, file)__\n\nEmitted whenever a new file is detected in the upload stream. Use this even if\nyou want to stream the file to somewhere else while buffering the upload on\nthe file system.\n\n__Event: 'file' (name, file)__\n\nEmitted whenever a field / file pair has been received. `file` is an instance of `File`.\n\n__Event: 'error' (err)__\n\nEmitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.\n\n__Event: 'aborted'__\n\nEmitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).\n\n__Event: 'end' ()__\n\nEmitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.\n\n### formidable.File\n\n__file.size = 0__\n\nThe size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.\n\n__file.path = null__\n\nThe path this file is being written to. You can modify this in the `'fileBegin'` event in\ncase you are unhappy with the way formidable generates a temporary path for your files.\n\n__file.name = null__\n\nThe name this file had according to the uploading client.\n\n__file.type = null__\n\nThe mime type of this file, according to the uploading client.\n\n__file.lastModifiedDate = null__\n\nA date object (or `null`) containing the time this file was last written to. Mostly\nhere for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).\n\n__file.hash = null__\n\nIf hash calculation was set, you can read the hex digest out of this var.\n\n## License\n\nFormidable is licensed under the MIT license.\n\n## Ports\n\n* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable\n\n## Credits\n\n* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js\n", + "_id": "formidable@1.0.11", + "description": "[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)", + "_from": "formidable@1.0.11" +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js new file mode 100644 index 0000000..eb432ad --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js @@ -0,0 +1,19 @@ +var mysql = require('..'); +var path = require('path'); + +var root = path.join(__dirname, '../'); +exports.dir = { + root : root, + lib : root + '/lib', + fixture : root + '/test/fixture', + tmp : root + '/test/tmp', +}; + +exports.port = 13532; + +exports.formidable = require('..'); +exports.assert = require('assert'); + +exports.require = function(lib) { + return require(exports.dir.lib + '/' + lib); +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt new file mode 100644 index 0000000..e7a4785 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt @@ -0,0 +1 @@ +I am a text file with a funky name! diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt new file mode 100644 index 0000000..9b6903e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt @@ -0,0 +1 @@ +I am a plain text file diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md new file mode 100644 index 0000000..3c9dbe3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md @@ -0,0 +1,3 @@ +* Opera does not allow submitting this file, it shows a warning to the + user that the file could not be found instead. Tested in 9.8, 11.51 on OSX. + Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com). diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js new file mode 100644 index 0000000..0bae449 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js @@ -0,0 +1,3 @@ +module.exports['generic.http'] = [ + {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt'}, +]; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js new file mode 100644 index 0000000..eb76fdc --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js @@ -0,0 +1,21 @@ +var properFilename = 'funkyfilename.txt'; + +function expect(filename) { + return [ + {type: 'field', name: 'title', value: 'Weird filename'}, + {type: 'file', name: 'upload', filename: filename, fixture: properFilename}, + ]; +}; + +var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; +var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; + +module.exports = { + 'osx-chrome-13.http' : expect(webkit), + 'osx-firefox-3.6.http' : expect(ffOrIe), + 'osx-safari-5.http' : expect(webkit), + 'xp-chrome-12.http' : expect(webkit), + 'xp-ie-7.http' : expect(ffOrIe), + 'xp-ie-8.http' : expect(ffOrIe), + 'xp-safari-5.http' : expect(webkit), +}; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js new file mode 100644 index 0000000..a476169 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js @@ -0,0 +1,72 @@ +exports['rfc1867'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['noTrailing\r\n'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--', + parts: + [ { headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + } + ] + }; + +exports['emptyHeader'] = + { boundary: 'AaB03x', + raw: + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="field1"\r\n'+ + ': foo\r\n'+ + '\r\n'+ + 'Joe Blow\r\nalmost tricked you!\r\n'+ + '--AaB03x\r\n'+ + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ + 'Content-Type: text/plain\r\n'+ + '\r\n'+ + '... contents of file1.txt ...\r\r\n'+ + '--AaB03x--\r\n', + expectError: true, + }; diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js new file mode 100644 index 0000000..66ad259 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js @@ -0,0 +1,89 @@ +var hashish = require('hashish'); +var fs = require('fs'); +var findit = require('findit'); +var path = require('path'); +var http = require('http'); +var net = require('net'); +var assert = require('assert'); + +var common = require('../common'); +var formidable = common.formidable; + +var server = http.createServer(); +server.listen(common.port, findFixtures); + +function findFixtures() { + var fixtures = []; + findit + .sync(common.dir.fixture + '/js') + .forEach(function(jsPath) { + if (!/\.js$/.test(jsPath)) return; + + var group = path.basename(jsPath, '.js'); + hashish.forEach(require(jsPath), function(fixture, name) { + fixtures.push({ + name : group + '/' + name, + fixture : fixture, + }); + }); + }); + + testNext(fixtures); +} + +function testNext(fixtures) { + var fixture = fixtures.shift(); + if (!fixture) return server.close(); + + var name = fixture.name; + var fixture = fixture.fixture; + + uploadFixture(name, function(err, parts) { + if (err) throw err; + + fixture.forEach(function(expectedPart, i) { + var parsedPart = parts[i]; + assert.equal(parsedPart.type, expectedPart.type); + assert.equal(parsedPart.name, expectedPart.name); + + if (parsedPart.type === 'file') { + var filename = parsedPart.value.name; + assert.equal(filename, expectedPart.filename); + } + }); + + testNext(fixtures); + }); +}; + +function uploadFixture(name, cb) { + server.once('request', function(req, res) { + var form = new formidable.IncomingForm(); + form.uploadDir = common.dir.tmp; + form.parse(req); + + function callback() { + var realCallback = cb; + cb = function() {}; + realCallback.apply(null, arguments); + } + + var parts = []; + form + .on('error', callback) + .on('fileBegin', function(name, value) { + parts.push({type: 'file', name: name, value: value}); + }) + .on('field', function(name, value) { + parts.push({type: 'field', name: name, value: value}); + }) + .on('end', function() { + callback(null, parts); + }); + }); + + var socket = net.createConnection(common.port); + var file = fs.createReadStream(common.dir.fixture + '/http/' + name); + + file.pipe(socket); +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js new file mode 100644 index 0000000..2b98598 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js @@ -0,0 +1,24 @@ +var path = require('path'), + fs = require('fs'); + +try { + global.Gently = require('gently'); +} catch (e) { + throw new Error('this test suite requires node-gently'); +} + +exports.lib = path.join(__dirname, '../../lib'); + +global.GENTLY = new Gently(); + +global.assert = require('assert'); +global.TEST_PORT = 13532; +global.TEST_FIXTURES = path.join(__dirname, '../fixture'); +global.TEST_TMP = path.join(__dirname, '../tmp'); + +// Stupid new feature in node that complains about gently attaching too many +// listeners to process 'exit'. This is a workaround until I can think of a +// better way to deal with this. +if (process.setMaxListeners) { + process.setMaxListeners(10000); +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js new file mode 100644 index 0000000..75232aa --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js @@ -0,0 +1,80 @@ +var common = require('../common'); +var CHUNK_LENGTH = 10, + multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + parser = new MultipartParser(), + fixtures = require(TEST_FIXTURES + '/multipart'), + Buffer = require('buffer').Buffer; + +Object.keys(fixtures).forEach(function(name) { + var fixture = fixtures[name], + buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')), + offset = 0, + chunk, + nparsed, + + parts = [], + part = null, + headerField, + headerValue, + endCalled = ''; + + parser.initWithBoundary(fixture.boundary); + parser.onPartBegin = function() { + part = {headers: {}, data: ''}; + parts.push(part); + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString('ascii', start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString('ascii', start, end); + } + + parser.onHeaderEnd = function() { + part.headers[headerField] = headerValue; + headerField = ''; + headerValue = ''; + }; + + parser.onPartData = function(b, start, end) { + var str = b.toString('ascii', start, end); + part.data += b.slice(start, end); + } + + parser.onEnd = function() { + endCalled = true; + } + + buffer.write(fixture.raw, 'binary', 0); + + while (offset < buffer.length) { + if (offset + CHUNK_LENGTH < buffer.length) { + chunk = buffer.slice(offset, offset+CHUNK_LENGTH); + } else { + chunk = buffer.slice(offset, buffer.length); + } + offset = offset + CHUNK_LENGTH; + + nparsed = parser.write(chunk); + if (nparsed != chunk.length) { + if (fixture.expectError) { + return; + } + puts('-- ERROR --'); + p(chunk.toString('ascii')); + throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!'); + } + } + + if (fixture.expectError) { + throw new Error('expected parse error did not happen'); + } + + assert.ok(endCalled); + assert.deepEqual(parts, fixture.parts); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js new file mode 100644 index 0000000..52ceedb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js @@ -0,0 +1,104 @@ +var common = require('../common'); +var WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); + +var File = require(common.lib + '/file'), + EventEmitter = require('events').EventEmitter, + file, + gently; + +function test(test) { + gently = new Gently(); + file = new File(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.ok(file instanceof EventEmitter); + assert.strictEqual(file.size, 0); + assert.strictEqual(file.path, null); + assert.strictEqual(file.name, null); + assert.strictEqual(file.type, null); + assert.strictEqual(file.lastModifiedDate, null); + + assert.strictEqual(file._writeStream, null); + + (function testSetProperties() { + var file2 = new File({foo: 'bar'}); + assert.equal(file2.foo, 'bar'); + })(); +}); + +test(function open() { + var WRITE_STREAM; + file.path = '/foo'; + + gently.expect(WriteStreamStub, 'new', function (path) { + WRITE_STREAM = this; + assert.strictEqual(path, file.path); + }); + + file.open(); + assert.strictEqual(file._writeStream, WRITE_STREAM); +}); + +test(function write() { + var BUFFER = {length: 10}, + CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'write', function (buffer, cb) { + assert.strictEqual(buffer, BUFFER); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.ok(file.lastModifiedDate instanceof Date); + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 10); + }); + + cb(); + + gently.expect(file, 'emit', function (event, bytesWritten) { + assert.equal(event, 'progress'); + assert.equal(bytesWritten, file.size); + }); + + CB_STUB = gently.expect(function writeCb() { + assert.equal(file.size, 20); + }); + + cb(); + }); + + file.write(BUFFER, CB); +}); + +test(function end() { + var CB_STUB, + CB = function() { + CB_STUB.apply(this, arguments); + }; + + file._writeStream = {}; + + gently.expect(file._writeStream, 'end', function (cb) { + gently.expect(file, 'emit', function (event) { + assert.equal(event, 'end'); + }); + + CB_STUB = gently.expect(function endCb() { + }); + + cb(); + }); + + file.end(CB); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js new file mode 100644 index 0000000..84de439 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js @@ -0,0 +1,727 @@ +var common = require('../common'); +var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'), + QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'), + EventEmitterStub = GENTLY.stub('events', 'EventEmitter'), + StreamStub = GENTLY.stub('stream', 'Stream'), + FileStub = GENTLY.stub('./file'); + +var formidable = require(common.lib + '/index'), + IncomingForm = formidable.IncomingForm, + events = require('events'), + fs = require('fs'), + path = require('path'), + Buffer = require('buffer').Buffer, + fixtures = require(TEST_FIXTURES + '/multipart'), + form, + gently; + +function test(test) { + gently = new Gently(); + gently.expect(EventEmitterStub, 'call'); + form = new IncomingForm(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.strictEqual(form.error, null); + assert.strictEqual(form.ended, false); + assert.strictEqual(form.type, null); + assert.strictEqual(form.headers, null); + assert.strictEqual(form.keepExtensions, false); + assert.strictEqual(form.uploadDir, '/tmp'); + assert.strictEqual(form.encoding, 'utf-8'); + assert.strictEqual(form.bytesReceived, null); + assert.strictEqual(form.bytesExpected, null); + assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024); + assert.strictEqual(form._parser, null); + assert.strictEqual(form._flushing, 0); + assert.strictEqual(form._fieldsSize, 0); + assert.ok(form instanceof EventEmitterStub); + assert.equal(form.constructor.name, 'IncomingForm'); + + (function testSimpleConstructor() { + gently.expect(EventEmitterStub, 'call'); + var form = IncomingForm(); + assert.ok(form instanceof IncomingForm); + })(); + + (function testSimpleConstructorShortcut() { + gently.expect(EventEmitterStub, 'call'); + var form = formidable(); + assert.ok(form instanceof IncomingForm); + })(); +}); + +test(function parse() { + var REQ = {headers: {}} + , emit = {}; + + gently.expect(form, 'writeHeaders', function(headers) { + assert.strictEqual(headers, REQ.headers); + }); + + var events = ['error', 'aborted', 'data', 'end']; + gently.expect(REQ, 'on', events.length, function(event, fn) { + assert.equal(event, events.shift()); + emit[event] = fn; + return this; + }); + + form.parse(REQ); + + (function testPause() { + gently.expect(REQ, 'pause'); + assert.strictEqual(form.pause(), true); + })(); + + (function testPauseCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testPauseHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'pause', function() { + throw ERR; + }); + + assert.strictEqual(form.pause(), false); + })(); + + (function testResume() { + gently.expect(REQ, 'resume'); + assert.strictEqual(form.resume(), true); + })(); + + (function testResumeCriticalException() { + form.ended = false; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testResumeHarmlessException() { + form.ended = true; + + var ERR = new Error('dasdsa'); + gently.expect(REQ, 'resume', function() { + throw ERR; + }); + + assert.strictEqual(form.resume(), false); + })(); + + (function testEmitError() { + var ERR = new Error('something bad happened'); + gently.expect(form, '_error',function(err) { + assert.strictEqual(err, ERR); + }); + emit.error(ERR); + })(); + + (function testEmitAborted() { + gently.expect(form, 'emit',function(event) { + assert.equal(event, 'aborted'); + }); + + emit.aborted(); + })(); + + + (function testEmitData() { + var BUFFER = [1, 2, 3]; + gently.expect(form, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + }); + emit.data(BUFFER); + })(); + + (function testEmitEnd() { + form._parser = {}; + + (function testWithError() { + var ERR = new Error('haha'); + gently.expect(form._parser, 'end', function() { + return ERR; + }); + + gently.expect(form, '_error', function(err) { + assert.strictEqual(err, ERR); + }); + + emit.end(); + })(); + + (function testWithoutError() { + gently.expect(form._parser, 'end'); + emit.end(); + })(); + + (function testAfterError() { + form.error = true; + emit.end(); + })(); + })(); + + (function testWithCallback() { + gently.expect(EventEmitterStub, 'call'); + var form = new IncomingForm(), + REQ = {headers: {}}, + parseCalled = 0; + + gently.expect(form, 'writeHeaders'); + gently.expect(REQ, 'on', 4, function() { + return this; + }); + + gently.expect(form, 'on', 4, function(event, fn) { + if (event == 'field') { + fn('field1', 'foo'); + fn('field1', 'bar'); + fn('field2', 'nice'); + } + + if (event == 'file') { + fn('file1', '1'); + fn('file1', '2'); + fn('file2', '3'); + } + + if (event == 'end') { + fn(); + } + return this; + }); + + form.parse(REQ, gently.expect(function parseCbOk(err, fields, files) { + assert.deepEqual(fields, {field1: 'bar', field2: 'nice'}); + assert.deepEqual(files, {file1: '2', file2: '3'}); + })); + + gently.expect(form, 'writeHeaders'); + gently.expect(REQ, 'on', 4, function() { + return this; + }); + + var ERR = new Error('test'); + gently.expect(form, 'on', 3, function(event, fn) { + if (event == 'field') { + fn('foo', 'bar'); + } + + if (event == 'error') { + fn(ERR); + gently.expect(form, 'on'); + } + return this; + }); + + form.parse(REQ, gently.expect(function parseCbErr(err, fields, files) { + assert.strictEqual(err, ERR); + assert.deepEqual(fields, {foo: 'bar'}); + })); + })(); +}); + +test(function pause() { + assert.strictEqual(form.pause(), false); +}); + +test(function resume() { + assert.strictEqual(form.resume(), false); +}); + + +test(function writeHeaders() { + var HEADERS = {}; + gently.expect(form, '_parseContentLength'); + gently.expect(form, '_parseContentType'); + + form.writeHeaders(HEADERS); + assert.strictEqual(form.headers, HEADERS); +}); + +test(function write() { + var parser = {}, + BUFFER = [1, 2, 3]; + + form._parser = parser; + form.bytesExpected = 523423; + + (function testBasic() { + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, BUFFER.length); + assert.equal(bytesExpected, form.bytesExpected); + }); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length; + }); + + assert.equal(form.write(BUFFER), BUFFER.length); + assert.equal(form.bytesReceived, BUFFER.length); + })(); + + (function testParserError() { + gently.expect(form, 'emit'); + + gently.expect(parser, 'write', function(buffer) { + assert.strictEqual(buffer, BUFFER); + return buffer.length - 1; + }); + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/parser error/i)); + }); + + assert.equal(form.write(BUFFER), BUFFER.length - 1); + assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length); + })(); + + (function testUninitialized() { + delete form._parser; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unintialized parser/i)); + }); + form.write(BUFFER); + })(); +}); + +test(function parseContentType() { + var HEADERS = {}; + + form.headers = {'content-type': 'application/x-www-form-urlencoded'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + // accept anything that has 'urlencoded' in it + form.headers = {'content-type': 'broken-client/urlencoded-stupid'}; + gently.expect(form, '_initUrlencoded'); + form._parseContentType(); + + var BOUNDARY = '---------------------------57814261102167618332366269'; + form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + + (function testQuotedBoundary() { + form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'}; + + gently.expect(form, '_initMultipart', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + form._parseContentType(); + })(); + + (function testNoBoundary() { + form.headers = {'content-type': 'multipart/form-data'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no multipart boundary/i)); + }); + form._parseContentType(); + })(); + + (function testNoContentType() { + form.headers = {}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/no content-type/i)); + }); + form._parseContentType(); + })(); + + (function testUnknownContentType() { + form.headers = {'content-type': 'invalid'}; + + gently.expect(form, '_error', function(err) { + assert.ok(err.message.match(/unknown content-type/i)); + }); + form._parseContentType(); + })(); +}); + +test(function parseContentLength() { + var HEADERS = {}; + + form.headers = {}; + form._parseContentLength(); + assert.strictEqual(form.bytesReceived, null); + assert.strictEqual(form.bytesExpected, null); + + form.headers['content-length'] = '8'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesReceived, 0); + assert.strictEqual(form.bytesExpected, 8); + + // JS can be evil, lets make sure we are not + form.headers['content-length'] = '08'; + gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { + assert.equal(event, 'progress'); + assert.equal(bytesReceived, 0); + assert.equal(bytesExpected, 8); + }); + form._parseContentLength(); + assert.strictEqual(form.bytesExpected, 8); +}); + +test(function _initMultipart() { + var BOUNDARY = '123', + PARSER; + + gently.expect(MultipartParserStub, 'new', function() { + PARSER = this; + }); + + gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) { + assert.equal(boundary, BOUNDARY); + }); + + form._initMultipart(BOUNDARY); + assert.equal(form.type, 'multipart'); + assert.strictEqual(form._parser, PARSER); + + (function testRegularField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.strictEqual(part, PART); + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field1"' + , 'foo': 'bar' + } + ); + assert.equal(part.name, 'field1'); + + var strings = ['hello', ' world']; + gently.expect(part, 'emit', 2, function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), strings.shift()); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10); + PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14); + PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('foo'), 0, 3); + PARSER.onHeaderValue(new Buffer('bar'), 0, 3); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('hello world'), 0, 5); + PARSER.onPartData(new Buffer('hello world'), 5, 11); + PARSER.onPartEnd(); + })(); + + (function testFileField() { + var PART; + gently.expect(StreamStub, 'new', function() { + PART = this; + }); + + gently.expect(form, 'onPart', function(part) { + assert.deepEqual + ( part.headers + , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"' + , 'content-type': 'text/plain' + } + ); + assert.equal(part.name, 'field2'); + assert.equal(part.filename, 'Sun"et.jpg'); + assert.equal(part.mime, 'text/plain'); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'data'); + assert.equal(b.toString(), '... contents of file1.txt ...'); + }); + + gently.expect(part, 'emit', function(event, b) { + assert.equal(event, 'end'); + }); + }); + + PARSER.onPartBegin(); + PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19); + PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85); + PARSER.onHeaderEnd(); + PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12); + PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10); + PARSER.onHeaderEnd(); + PARSER.onHeadersEnd(); + PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29); + PARSER.onPartEnd(); + })(); + + (function testEnd() { + gently.expect(form, '_maybeEnd'); + PARSER.onEnd(); + assert.ok(form.ended); + })(); +}); + +test(function _fileName() { + // TODO + return; +}); + +test(function _initUrlencoded() { + var PARSER; + + gently.expect(QuerystringParserStub, 'new', function() { + PARSER = this; + }); + + form._initUrlencoded(); + assert.equal(form.type, 'urlencoded'); + assert.strictEqual(form._parser, PARSER); + + (function testOnField() { + var KEY = 'KEY', VAL = 'VAL'; + gently.expect(form, 'emit', function(field, key, val) { + assert.equal(field, 'field'); + assert.equal(key, KEY); + assert.equal(val, VAL); + }); + + PARSER.onField(KEY, VAL); + })(); + + (function testOnEnd() { + gently.expect(form, '_maybeEnd'); + + PARSER.onEnd(); + assert.equal(form.ended, true); + })(); +}); + +test(function _error() { + var ERR = new Error('bla'); + + gently.expect(form, 'pause'); + gently.expect(form, 'emit', function(event, err) { + assert.equal(event, 'error'); + assert.strictEqual(err, ERR); + }); + + form._error(ERR); + assert.strictEqual(form.error, ERR); + + // make sure _error only does its thing once + form._error(ERR); +}); + +test(function onPart() { + var PART = {}; + gently.expect(form, 'handlePart', function(part) { + assert.strictEqual(part, PART); + }); + + form.onPart(PART); +}); + +test(function handlePart() { + (function testUtf8Field() { + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field'); + assert.equal(value, 'hello world: €'); + }); + + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testBinaryField() { + var PART = new events.EventEmitter(); + PART.name = 'my_field2'; + + gently.expect(form, 'emit', function(event, field, value) { + assert.equal(event, 'field'); + assert.equal(field, 'my_field2'); + assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary')); + }); + + form.encoding = 'binary'; + form.handlePart(PART); + PART.emit('data', new Buffer('hello')); + PART.emit('data', new Buffer(' world: ')); + PART.emit('data', new Buffer([0xE2])); + PART.emit('data', new Buffer([0x82, 0xAC])); + PART.emit('end'); + })(); + + (function testFieldSize() { + form.maxFieldsSize = 8; + var PART = new events.EventEmitter(); + PART.name = 'my_field'; + + gently.expect(form, '_error', function(err) { + assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data'); + }); + + form.handlePart(PART); + form._fieldsSize = 1; + PART.emit('data', new Buffer(7)); + PART.emit('data', new Buffer(1)); + })(); + + (function testFilePart() { + var PART = new events.EventEmitter(), + FILE = new events.EventEmitter(), + PATH = '/foo/bar'; + + PART.name = 'my_file'; + PART.filename = 'sweet.txt'; + PART.mime = 'sweet.txt'; + + gently.expect(form, '_uploadPath', function(filename) { + assert.equal(filename, PART.filename); + return PATH; + }); + + gently.expect(FileStub, 'new', function(properties) { + assert.equal(properties.path, PATH); + assert.equal(properties.name, PART.filename); + assert.equal(properties.type, PART.mime); + FILE = this; + + gently.expect(form, 'emit', function (event, field, file) { + assert.equal(event, 'fileBegin'); + assert.strictEqual(field, PART.name); + assert.strictEqual(file, FILE); + }); + + gently.expect(FILE, 'open'); + }); + + form.handlePart(PART); + assert.equal(form._flushing, 1); + + var BUFFER; + gently.expect(form, 'pause'); + gently.expect(FILE, 'write', function(buffer, cb) { + assert.strictEqual(buffer, BUFFER); + gently.expect(form, 'resume'); + // @todo handle cb(new Err) + cb(); + }); + + PART.emit('data', BUFFER = new Buffer('test')); + + gently.expect(FILE, 'end', function(cb) { + gently.expect(form, 'emit', function(event, field, file) { + assert.equal(event, 'file'); + assert.strictEqual(file, FILE); + }); + + gently.expect(form, '_maybeEnd'); + + cb(); + assert.equal(form._flushing, 0); + }); + + PART.emit('end'); + })(); +}); + +test(function _uploadPath() { + (function testUniqueId() { + var UUID_A, UUID_B; + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + assert.equal(uploadDir, form.uploadDir); + UUID_A = uuid; + }); + form._uploadPath(); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { + UUID_B = uuid; + }); + form._uploadPath(); + + assert.notEqual(UUID_A, UUID_B); + })(); + + (function testFileExtension() { + form.keepExtensions = true; + var FILENAME = 'foo.jpg', + EXT = '.bar'; + + gently.expect(GENTLY.hijacked.path, 'extname', function(filename) { + assert.equal(filename, FILENAME); + gently.restore(path, 'extname'); + + return EXT; + }); + + gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) { + assert.equal(path.extname(name), EXT); + }); + form._uploadPath(FILENAME); + })(); +}); + +test(function _maybeEnd() { + gently.expect(form, 'emit', 0); + form._maybeEnd(); + + form.ended = true; + form._flushing = 1; + form._maybeEnd(); + + gently.expect(form, 'emit', function(event) { + assert.equal(event, 'end'); + }); + + form.ended = true; + form._flushing = 0; + form._maybeEnd(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js new file mode 100644 index 0000000..d8dc968 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js @@ -0,0 +1,50 @@ +var common = require('../common'); +var multipartParser = require(common.lib + '/multipart_parser'), + MultipartParser = multipartParser.MultipartParser, + events = require('events'), + Buffer = require('buffer').Buffer, + parser; + +function test(test) { + parser = new MultipartParser(); + test(); +} + +test(function constructor() { + assert.equal(parser.boundary, null); + assert.equal(parser.state, 0); + assert.equal(parser.flags, 0); + assert.equal(parser.boundaryChars, null); + assert.equal(parser.index, null); + assert.equal(parser.lookbehind, null); + assert.equal(parser.constructor.name, 'MultipartParser'); +}); + +test(function initWithBoundary() { + var boundary = 'abc'; + parser.initWithBoundary(boundary); + assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]); + assert.equal(parser.state, multipartParser.START); + + assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true}); +}); + +test(function parserError() { + var boundary = 'abc', + buffer = new Buffer(5); + + parser.initWithBoundary(boundary); + buffer.write('--ad', 'ascii', 0); + assert.equal(parser.write(buffer), 3); +}); + +test(function end() { + (function testError() { + assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain()); + })(); + + (function testRegular() { + parser.state = multipartParser.END; + assert.strictEqual(parser.end(), undefined); + })(); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js new file mode 100644 index 0000000..54d3e2d --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js @@ -0,0 +1,45 @@ +var common = require('../common'); +var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser, + Buffer = require('buffer').Buffer, + gently, + parser; + +function test(test) { + gently = new Gently(); + parser = new QuerystringParser(); + test(); + gently.verify(test.name); +} + +test(function constructor() { + assert.equal(parser.buffer, ''); + assert.equal(parser.constructor.name, 'QuerystringParser'); +}); + +test(function write() { + var a = new Buffer('a=1'); + assert.equal(parser.write(a), a.length); + + var b = new Buffer('&b=2'); + parser.write(b); + assert.equal(parser.buffer, a + b); +}); + +test(function end() { + var FIELDS = {a: ['b', {c: 'd'}], e: 'f'}; + + gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) { + assert.equal(str, parser.buffer); + return FIELDS; + }); + + gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) { + assert.deepEqual(FIELDS[key], val); + }); + + gently.expect(parser, 'onEnd'); + + parser.buffer = 'my buffer'; + parser.end(); + assert.equal(parser.buffer, ''); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js new file mode 100644 index 0000000..479e46d --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js @@ -0,0 +1,75 @@ +var common = require('../common'); +var BOUNDARY = '---------------------------10102754414578508781458777923', + FIXTURE = TEST_FIXTURES+'/multi_video.upload', + fs = require('fs'), + util = require(common.lib + '/util'), + http = require('http'), + formidable = require(common.lib + '/index'), + server = http.createServer(); + +server.on('request', function(req, res) { + var form = new formidable.IncomingForm(), + uploads = {}; + + form.uploadDir = TEST_TMP; + form.hash = 'sha1'; + form.parse(req); + + form + .on('fileBegin', function(field, file) { + assert.equal(field, 'upload'); + + var tracker = {file: file, progress: [], ended: false}; + uploads[file.filename] = tracker; + file + .on('progress', function(bytesReceived) { + tracker.progress.push(bytesReceived); + assert.equal(bytesReceived, file.length); + }) + .on('end', function() { + tracker.ended = true; + }); + }) + .on('field', function(field, value) { + assert.equal(field, 'title'); + assert.equal(value, ''); + }) + .on('file', function(field, file) { + assert.equal(field, 'upload'); + assert.strictEqual(uploads[file.filename].file, file); + }) + .on('end', function() { + assert.ok(uploads['shortest_video.flv']); + assert.ok(uploads['shortest_video.flv'].ended); + assert.ok(uploads['shortest_video.flv'].progress.length > 3); + assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a'); + assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.length); + assert.ok(uploads['shortest_video.mp4']); + assert.ok(uploads['shortest_video.mp4'].ended); + assert.ok(uploads['shortest_video.mp4'].progress.length > 3); + assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f'); + + server.close(); + res.writeHead(200); + res.end('good'); + }); +}); + +server.listen(TEST_PORT, function() { + var client = http.createClient(TEST_PORT), + stat = fs.statSync(FIXTURE), + headers = { + 'content-type': 'multipart/form-data; boundary='+BOUNDARY, + 'content-length': stat.size, + } + request = client.request('POST', '/', headers), + fixture = new fs.ReadStream(FIXTURE); + + fixture + .on('data', function(b) { + request.write(b); + }) + .on('end', function() { + request.end(); + }); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js new file mode 100755 index 0000000..50b2361 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('urun')(__dirname) diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js new file mode 100644 index 0000000..fe2ac1c --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js @@ -0,0 +1,63 @@ +var common = require('../common'); +var test = require('utest'); +var assert = common.assert; +var IncomingForm = common.require('incoming_form').IncomingForm; +var path = require('path'); + +var form; +test('IncomingForm', { + before: function() { + form = new IncomingForm(); + }, + + '#_fileName with regular characters': function() { + var filename = 'foo.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'foo.txt'); + }, + + '#_fileName with unescaped quote': function() { + var filename = 'my".txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with escaped quote': function() { + var filename = 'my%22.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); + }, + + '#_fileName with bad quote and additional sub-header': function() { + var filename = 'my".txt'; + var header = makeHeader(filename) + '; foo="bar"'; + assert.equal(form._fileName(header), filename); + }, + + '#_fileName with semicolon': function() { + var filename = 'my;.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my;.txt'); + }, + + '#_fileName with utf8 character': function() { + var filename = 'my☃.txt'; + assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt'); + }, + + '#_uploadPath strips harmful characters from extension when keepExtensions': function() { + form.keepExtensions = true; + + var ext = path.extname(form._uploadPath('fine.jpg?foo=bar')); + assert.equal(ext, '.jpg'); + + var ext = path.extname(form._uploadPath('fine?foo=bar')); + assert.equal(ext, ''); + + var ext = path.extname(form._uploadPath('super.cr2+dsad')); + assert.equal(ext, '.cr2'); + + var ext = path.extname(form._uploadPath('super.bar')); + assert.equal(ext, '.bar'); + }, +}); + +function makeHeader(filename) { + return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"'; +} diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js new file mode 100644 index 0000000..9f1cef8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js @@ -0,0 +1,47 @@ +var http = require('http'); +var fs = require('fs'); +var connections = 0; + +var server = http.createServer(function(req, res) { + var socket = req.socket; + console.log('Request: %s %s -> %s', req.method, req.url, socket.filename); + + req.on('end', function() { + if (req.url !== '/') { + res.end(JSON.stringify({ + method: req.method, + url: req.url, + filename: socket.filename, + })); + return; + } + + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '
    '+ + '
    '+ + '
    '+ + ''+ + '
    ' + ); + }); +}); + +server.on('connection', function(socket) { + connections++; + + socket.id = connections; + socket.filename = 'connection-' + socket.id + '.http'; + socket.file = fs.createWriteStream(socket.filename); + socket.pipe(socket.file); + + console.log('--> %s', socket.filename); + socket.on('close', function() { + console.log('<-- %s', socket.filename); + }); +}); + +var port = process.env.PORT || 8080; +server.listen(port, function() { + console.log('Recording connections on port %s', port); +}); diff --git a/node_modules/express/node_modules/connect/node_modules/pause/.npmignore b/node_modules/express/node_modules/connect/node_modules/pause/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/connect/node_modules/pause/History.md b/node_modules/express/node_modules/connect/node_modules/pause/History.md new file mode 100644 index 0000000..c8aa68f --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/History.md @@ -0,0 +1,5 @@ + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/connect/node_modules/pause/Makefile b/node_modules/express/node_modules/connect/node_modules/pause/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/Readme.md b/node_modules/express/node_modules/connect/node_modules/pause/Readme.md new file mode 100644 index 0000000..1cdd68a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/Readme.md @@ -0,0 +1,29 @@ + +# pause + + Pause streams... + +## License + +(The MIT License) + +Copyright (c) 2012 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. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/index.js b/node_modules/express/node_modules/connect/node_modules/pause/index.js new file mode 100644 index 0000000..1b7b379 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/index.js @@ -0,0 +1,29 @@ + +module.exports = function(obj){ + var onData + , onEnd + , events = []; + + // buffer data + obj.on('data', onData = function(data, encoding){ + events.push(['data', data, encoding]); + }); + + // buffer end + obj.on('end', onEnd = function(data, encoding){ + events.push(['end', data, encoding]); + }); + + return { + end: function(){ + obj.removeListener('data', onData); + obj.removeListener('end', onEnd); + }, + resume: function(){ + this.end(); + for (var i = 0, len = events.length; i < len; ++i) { + obj.emit.apply(obj, events[i]); + } + } + }; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/pause/package.json b/node_modules/express/node_modules/connect/node_modules/pause/package.json new file mode 100644 index 0000000..1b66942 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/pause/package.json @@ -0,0 +1,19 @@ +{ + "name": "pause", + "version": "0.0.1", + "description": "Pause streams...", + "keywords": [], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "main": "index", + "readme": "\n# pause\n\n Pause streams...\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "_id": "pause@0.0.1", + "_from": "pause@0.0.1" +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules b/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules new file mode 100644 index 0000000..49e31da --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.npmignore b/node_modules/express/node_modules/connect/node_modules/qs/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/express/node_modules/connect/node_modules/qs/.travis.yml b/node_modules/express/node_modules/connect/node_modules/qs/.travis.yml new file mode 100644 index 0000000..2c0a8f6 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.4 \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/History.md b/node_modules/express/node_modules/connect/node_modules/qs/History.md new file mode 100644 index 0000000..1feef45 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/History.md @@ -0,0 +1,83 @@ + +0.5.1 / 2012-09-18 +================== + + * fix encoded `=`. Closes #43 + +0.5.0 / 2012-05-04 +================== + + * Added component support + +0.4.2 / 2012-02-08 +================== + + * Fixed: ensure objects are created when appropriate not arrays [aheckmann] + +0.4.1 / 2012-01-26 +================== + + * Fixed stringify()ing numbers. Closes #23 + +0.4.0 / 2011-11-21 +================== + + * Allow parsing of an existing object (for `bodyParser()`) [jackyz] + * Replaced expresso with mocha + +0.3.2 / 2011-11-08 +================== + + * Fixed global variable leak + +0.3.1 / 2011-08-17 +================== + + * Added `try/catch` around malformed uri components + * Add test coverage for Array native method bleed-though + +0.3.0 / 2011-07-19 +================== + + * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart] + +0.2.0 / 2011-06-29 +================== + + * Added `qs.stringify()` [Cory Forsyth] + +0.1.0 / 2011-04-13 +================== + + * Added jQuery-ish array support + +0.0.7 / 2011-03-13 +================== + + * Fixed; handle empty string and `== null` in `qs.parse()` [dmit] + allows for convenient `qs.parse(url.parse(str).query)` + +0.0.6 / 2011-02-14 +================== + + * Fixed; support for implicit arrays + +0.0.4 / 2011-02-09 +================== + + * Fixed `+` as a space + +0.0.3 / 2011-02-08 +================== + + * Fixed case when right-hand value contains "]" + +0.0.2 / 2011-02-07 +================== + + * Fixed "=" presence in key + +0.0.1 / 2011-02-07 +================== + + * Initial release \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/Makefile b/node_modules/express/node_modules/connect/node_modules/qs/Makefile new file mode 100644 index 0000000..0a21cf7 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/Makefile @@ -0,0 +1,12 @@ + +test/browser/qs.js: querystring.js + component build package.json test/browser/qs + +querystring.js: lib/head.js lib/querystring.js lib/tail.js + cat $^ > $@ + +test: + @./node_modules/.bin/mocha \ + --ui bdd + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/Readme.md b/node_modules/express/node_modules/connect/node_modules/qs/Readme.md new file mode 100644 index 0000000..27e54a4 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 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. \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/benchmark.js b/node_modules/express/node_modules/connect/node_modules/qs/benchmark.js new file mode 100644 index 0000000..97e2c93 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/benchmark.js @@ -0,0 +1,17 @@ + +var qs = require('./'); + +var times = 100000 + , start = new Date + , n = times; + +console.log('times: %d', times); + +while (n--) qs.parse('foo=bar'); +console.log('simple: %dms', new Date - start); + +var start = new Date + , n = times; + +while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log('nested: %dms', new Date - start); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/component.json b/node_modules/express/node_modules/connect/node_modules/qs/component.json new file mode 100644 index 0000000..ba34ead --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/component.json @@ -0,0 +1,6 @@ +{ + "name": "querystring", + "description": "Querystring parser / stringifier with nesting support", + "keywords": ["querystring", "query", "parser"], + "main": "lib/querystring.js" +} \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/examples.js b/node_modules/express/node_modules/connect/node_modules/qs/examples.js new file mode 100644 index 0000000..27617b7 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/examples.js @@ -0,0 +1,51 @@ + +/** + * Module dependencies. + */ + +var qs = require('./'); + +var obj = qs.parse('foo'); +console.log(obj) + +var obj = qs.parse('foo=bar=baz'); +console.log(obj) + +var obj = qs.parse('users[]'); +console.log(obj) + +var obj = qs.parse('name=tj&email=tj@vision-media.ca'); +console.log(obj) + +var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('a=a&a=b&a=c'); +console.log(obj) + +var obj = qs.parse('user[tj]=tj&user[tj]=TJ'); +console.log(obj) + +var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[1]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[foo]=TJ'); +console.log(obj) + +var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}); +console.log(str); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/index.js b/node_modules/express/node_modules/connect/node_modules/qs/index.js new file mode 100644 index 0000000..d177d20 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/querystring'); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/lib/head.js b/node_modules/express/node_modules/connect/node_modules/qs/lib/head.js new file mode 100644 index 0000000..55d3817 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/lib/head.js @@ -0,0 +1 @@ +;(function(){ diff --git a/node_modules/express/node_modules/connect/node_modules/qs/lib/querystring.js b/node_modules/express/node_modules/connect/node_modules/qs/lib/querystring.js new file mode 100644 index 0000000..d3689bb --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/lib/querystring.js @@ -0,0 +1,262 @@ + +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = {}; + var t = {}; + for (var i in parent[key]) t[i] = parent[key][i]; + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (Array.isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (Array.isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[Object.keys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~part.indexOf(']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~key.indexOf(']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && Array.isArray(parent.base)) { + var t = {}; + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + Object.keys(obj).forEach(function(name){ + merge(ret, name, obj[name]); + }); + return ret.base; +} + +/** + * Parse the given str. + */ + +function parseString(str){ + return String(str) + .split('&') + .reduce(function(ret, pair){ + var eql = pair.indexOf('=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(val.indexOf('=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + + return merge(ret, decode(key), decode(val)); + }, { base: {} }).base; +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (Array.isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + obj; + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '['+i+']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = Object.keys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (Array.isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/lib/tail.js b/node_modules/express/node_modules/connect/node_modules/qs/lib/tail.js new file mode 100644 index 0000000..158693a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/lib/tail.js @@ -0,0 +1 @@ +})(); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/package.json b/node_modules/express/node_modules/connect/node_modules/qs/package.json new file mode 100644 index 0000000..ebf4cc3 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/package.json @@ -0,0 +1,35 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.5.1", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "component": { + "scripts": { + "querystring": "querystring.js" + } + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "_id": "qs@0.5.1", + "_from": "qs@0.5.1" +} diff --git a/node_modules/express/node_modules/connect/node_modules/qs/querystring.js b/node_modules/express/node_modules/connect/node_modules/qs/querystring.js new file mode 100644 index 0000000..7466b06 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/querystring.js @@ -0,0 +1,254 @@ +;(function(){ + +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = {}; + var t = {}; + for (var i in parent[key]) t[i] = parent[key][i]; + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (Array.isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (Array.isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[Object.keys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~part.indexOf(']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~key.indexOf(']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && Array.isArray(parent.base)) { + var t = {}; + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + Object.keys(obj).forEach(function(name){ + merge(ret, name, obj[name]); + }); + return ret.base; +} + +/** + * Parse the given str. + */ + +function parseString(str){ + return String(str) + .split('&') + .reduce(function(ret, pair){ + try{ + pair = decodeURIComponent(pair.replace(/\+/g, ' ')); + } catch(e) { + // ignore + } + + var eql = pair.indexOf('=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(val.indexOf('=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + + return merge(ret, key, val); + }, { base: {} }).base; +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (Array.isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + obj; + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '['+i+']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = Object.keys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (Array.isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} +})(); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/test/browser/expect.js b/node_modules/express/node_modules/connect/node_modules/qs/test/browser/expect.js new file mode 100644 index 0000000..76aa4e8 --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/test/browser/expect.js @@ -0,0 +1,1202 @@ + +(function (global, module) { + + if ('undefined' == typeof module) { + var module = { exports: {} } + , exports = module.exports + } + + /** + * Exports. + */ + + module.exports = expect; + expect.Assertion = Assertion; + + /** + * Exports version. + */ + + expect.version = '0.1.2'; + + /** + * Possible assertion flags. + */ + + var flags = { + not: ['to', 'be', 'have', 'include', 'only'] + , to: ['be', 'have', 'include', 'only', 'not'] + , only: ['have'] + , have: ['own'] + , be: ['an'] + }; + + function expect (obj) { + return new Assertion(obj); + } + + /** + * Constructor + * + * @api private + */ + + function Assertion (obj, flag, parent) { + this.obj = obj; + this.flags = {}; + + if (undefined != parent) { + this.flags[flag] = true; + + for (var i in parent.flags) { + if (parent.flags.hasOwnProperty(i)) { + this.flags[i] = true; + } + } + } + + var $flags = flag ? flags[flag] : keys(flags) + , self = this + + if ($flags) { + for (var i = 0, l = $flags.length; i < l; i++) { + // avoid recursion + if (this.flags[$flags[i]]) continue; + + var name = $flags[i] + , assertion = new Assertion(this.obj, name, this) + + if ('function' == typeof Assertion.prototype[name]) { + // clone the function, make sure we dont touch the prot reference + var old = this[name]; + this[name] = function () { + return old.apply(self, arguments); + } + + for (var fn in Assertion.prototype) { + if (Assertion.prototype.hasOwnProperty(fn) && fn != name) { + this[name][fn] = bind(assertion[fn], assertion); + } + } + } else { + this[name] = assertion; + } + } + } + }; + + /** + * Performs an assertion + * + * @api private + */ + + Assertion.prototype.assert = function (truth, msg, error) { + var msg = this.flags.not ? error : msg + , ok = this.flags.not ? !truth : truth; + + if (!ok) { + throw new Error(msg); + } + + this.and = new Assertion(this.obj); + }; + + /** + * Check if the value is truthy + * + * @api public + */ + + Assertion.prototype.ok = function () { + this.assert( + !!this.obj + , 'expected ' + i(this.obj) + ' to be truthy' + , 'expected ' + i(this.obj) + ' to be falsy'); + }; + + /** + * Assert that the function throws. + * + * @param {Function|RegExp} callback, or regexp to match error string against + * @api public + */ + + Assertion.prototype.throwError = + Assertion.prototype.throwException = function (fn) { + expect(this.obj).to.be.a('function'); + + var thrown = false + , not = this.flags.not + + try { + this.obj(); + } catch (e) { + if ('function' == typeof fn) { + fn(e); + } else if ('object' == typeof fn) { + var subject = 'string' == typeof e ? e : e.message; + if (not) { + expect(subject).to.not.match(fn); + } else { + expect(subject).to.match(fn); + } + } + thrown = true; + } + + if ('object' == typeof fn && not) { + // in the presence of a matcher, ensure the `not` only applies to + // the matching. + this.flags.not = false; + } + + var name = this.obj.name || 'fn'; + this.assert( + thrown + , 'expected ' + name + ' to throw an exception' + , 'expected ' + name + ' not to throw an exception'); + }; + + /** + * Checks if the array is empty. + * + * @api public + */ + + Assertion.prototype.empty = function () { + var expectation; + + if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) { + if ('number' == typeof this.obj.length) { + expectation = !this.obj.length; + } else { + expectation = !keys(this.obj).length; + } + } else { + if ('string' != typeof this.obj) { + expect(this.obj).to.be.an('object'); + } + + expect(this.obj).to.have.property('length'); + expectation = !this.obj.length; + } + + this.assert( + expectation + , 'expected ' + i(this.obj) + ' to be empty' + , 'expected ' + i(this.obj) + ' to not be empty'); + return this; + }; + + /** + * Checks if the obj exactly equals another. + * + * @api public + */ + + Assertion.prototype.be = + Assertion.prototype.equal = function (obj) { + this.assert( + obj === this.obj + , 'expected ' + i(this.obj) + ' to equal ' + i(obj) + , 'expected ' + i(this.obj) + ' to not equal ' + i(obj)); + return this; + }; + + /** + * Checks if the obj sortof equals another. + * + * @api public + */ + + Assertion.prototype.eql = function (obj) { + this.assert( + expect.eql(obj, this.obj) + , 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) + , 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj)); + return this; + }; + + /** + * Assert within start to finish (inclusive). + * + * @param {Number} start + * @param {Number} finish + * @api public + */ + + Assertion.prototype.within = function (start, finish) { + var range = start + '..' + finish; + this.assert( + this.obj >= start && this.obj <= finish + , 'expected ' + i(this.obj) + ' to be within ' + range + , 'expected ' + i(this.obj) + ' to not be within ' + range); + return this; + }; + + /** + * Assert typeof / instance of + * + * @api public + */ + + Assertion.prototype.a = + Assertion.prototype.an = function (type) { + if ('string' == typeof type) { + // proper english in error msg + var n = /^[aeiou]/.test(type) ? 'n' : ''; + + // typeof with support for 'array' + this.assert( + 'array' == type ? isArray(this.obj) : + 'object' == type + ? 'object' == typeof this.obj && null !== this.obj + : type == typeof this.obj + , 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type + , 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type); + } else { + // instanceof + var name = type.name || 'supplied constructor'; + this.assert( + this.obj instanceof type + , 'expected ' + i(this.obj) + ' to be an instance of ' + name + , 'expected ' + i(this.obj) + ' not to be an instance of ' + name); + } + + return this; + }; + + /** + * Assert numeric value above _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.greaterThan = + Assertion.prototype.above = function (n) { + this.assert( + this.obj > n + , 'expected ' + i(this.obj) + ' to be above ' + n + , 'expected ' + i(this.obj) + ' to be below ' + n); + return this; + }; + + /** + * Assert numeric value below _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.lessThan = + Assertion.prototype.below = function (n) { + this.assert( + this.obj < n + , 'expected ' + i(this.obj) + ' to be below ' + n + , 'expected ' + i(this.obj) + ' to be above ' + n); + return this; + }; + + /** + * Assert string value matches _regexp_. + * + * @param {RegExp} regexp + * @api public + */ + + Assertion.prototype.match = function (regexp) { + this.assert( + regexp.exec(this.obj) + , 'expected ' + i(this.obj) + ' to match ' + regexp + , 'expected ' + i(this.obj) + ' not to match ' + regexp); + return this; + }; + + /** + * Assert property "length" exists and has value of _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.length = function (n) { + expect(this.obj).to.have.property('length'); + var len = this.obj.length; + this.assert( + n == len + , 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len + , 'expected ' + i(this.obj) + ' to not have a length of ' + len); + return this; + }; + + /** + * Assert property _name_ exists, with optional _val_. + * + * @param {String} name + * @param {Mixed} val + * @api public + */ + + Assertion.prototype.property = function (name, val) { + if (this.flags.own) { + this.assert( + Object.prototype.hasOwnProperty.call(this.obj, name) + , 'expected ' + i(this.obj) + ' to have own property ' + i(name) + , 'expected ' + i(this.obj) + ' to not have own property ' + i(name)); + return this; + } + + if (this.flags.not && undefined !== val) { + if (undefined === this.obj[name]) { + throw new Error(i(this.obj) + ' has no property ' + i(name)); + } + } else { + var hasProp; + try { + hasProp = name in this.obj + } catch (e) { + hasProp = undefined !== this.obj[name] + } + + this.assert( + hasProp + , 'expected ' + i(this.obj) + ' to have a property ' + i(name) + , 'expected ' + i(this.obj) + ' to not have a property ' + i(name)); + } + + if (undefined !== val) { + this.assert( + val === this.obj[name] + , 'expected ' + i(this.obj) + ' to have a property ' + i(name) + + ' of ' + i(val) + ', but got ' + i(this.obj[name]) + , 'expected ' + i(this.obj) + ' to not have a property ' + i(name) + + ' of ' + i(val)); + } + + this.obj = this.obj[name]; + return this; + }; + + /** + * Assert that the array contains _obj_ or string contains _obj_. + * + * @param {Mixed} obj|string + * @api public + */ + + Assertion.prototype.string = + Assertion.prototype.contain = function (obj) { + if ('string' == typeof this.obj) { + this.assert( + ~this.obj.indexOf(obj) + , 'expected ' + i(this.obj) + ' to contain ' + i(obj) + , 'expected ' + i(this.obj) + ' to not contain ' + i(obj)); + } else { + this.assert( + ~indexOf(this.obj, obj) + , 'expected ' + i(this.obj) + ' to contain ' + i(obj) + , 'expected ' + i(this.obj) + ' to not contain ' + i(obj)); + } + return this; + }; + + /** + * Assert exact keys or inclusion of keys by using + * the `.own` modifier. + * + * @param {Array|String ...} keys + * @api public + */ + + Assertion.prototype.key = + Assertion.prototype.keys = function ($keys) { + var str + , ok = true; + + $keys = isArray($keys) + ? $keys + : Array.prototype.slice.call(arguments); + + if (!$keys.length) throw new Error('keys required'); + + var actual = keys(this.obj) + , len = $keys.length; + + // Inclusion + ok = every($keys, function (key) { + return ~indexOf(actual, key); + }); + + // Strict + if (!this.flags.not && this.flags.only) { + ok = ok && $keys.length == actual.length; + } + + // Key string + if (len > 1) { + $keys = map($keys, function (key) { + return i(key); + }); + var last = $keys.pop(); + str = $keys.join(', ') + ', and ' + last; + } else { + str = i($keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (!this.flags.only ? 'include ' : 'only have ') + str; + + // Assertion + this.assert( + ok + , 'expected ' + i(this.obj) + ' to ' + str + , 'expected ' + i(this.obj) + ' to not ' + str); + + return this; + }; + + /** + * Function bind implementation. + */ + + function bind (fn, scope) { + return function () { + return fn.apply(scope, arguments); + } + } + + /** + * Array every compatibility + * + * @see bit.ly/5Fq1N2 + * @api public + */ + + function every (arr, fn, thisObj) { + var scope = thisObj || global; + for (var i = 0, j = arr.length; i < j; ++i) { + if (!fn.call(scope, arr[i], i, arr)) { + return false; + } + } + return true; + }; + + /** + * Array indexOf compatibility. + * + * @see bit.ly/a5Dxa2 + * @api public + */ + + function indexOf (arr, o, i) { + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(arr, o, i); + } + + if (arr.length === undefined) { + return -1; + } + + for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 + ; i < j && arr[i] !== o; i++); + + return j <= i ? -1 : i; + }; + + /** + * Inspects an object. + * + * @see taken from node.js `util` module (copyright Joyent, MIT license) + * @api private + */ + + function i (obj, showHidden, depth) { + var seen = []; + + function stylize (str) { + return str; + }; + + function format (value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value !== exports && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + return value.inspect(recurseTimes); + } + + // Primitive types cannot have properties + switch (typeof value) { + case 'undefined': + return stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return stylize(simple, 'string'); + + case 'number': + return stylize('' + value, 'number'); + + case 'boolean': + return stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return stylize('null', 'null'); + } + + // Look up the keys of the object. + var visible_keys = keys(value); + var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; + + // Functions without properties can be shortcutted. + if (typeof value === 'function' && $keys.length === 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + var name = value.name ? ': ' + value.name : ''; + return stylize('[Function' + name + ']', 'special'); + } + } + + // Dates without properties can be shortcutted + if (isDate(value) && $keys.length === 0) { + return stylize(value.toUTCString(), 'date'); + } + + var base, type, braces; + // Determine the object type + if (isArray(value)) { + type = 'Array'; + braces = ['[', ']']; + } else { + type = 'Object'; + braces = ['{', '}']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var n = value.name ? ': ' + value.name : ''; + base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; + } else { + base = ''; + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + value.toUTCString(); + } + + if ($keys.length === 0) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + return stylize('[Object]', 'special'); + } + } + + seen.push(value); + + var output = map($keys, function (key) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = stylize('[Getter/Setter]', 'special'); + } else { + str = stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = stylize('[Setter]', 'special'); + } + } + } + if (indexOf(visible_keys, key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (indexOf(seen, value[key]) < 0) { + if (recurseTimes === null) { + str = format(value[key]); + } else { + str = format(value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (isArray(value)) { + str = map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (type === 'Array' && key.match(/^\d+$/)) { + return str; + } + name = json.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = stylize(name, 'string'); + } + } + + return name + ': ' + str; + }); + + seen.pop(); + + var numLinesEst = 0; + var length = reduce(output, function (prev, cur) { + numLinesEst++; + if (indexOf(cur, '\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 50) { + output = braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + + } else { + output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + return output; + } + return format(obj, (typeof depth === 'undefined' ? 2 : depth)); + }; + + function isArray (ar) { + return Object.prototype.toString.call(ar) == '[object Array]'; + }; + + function isRegExp(re) { + var s = '' + re; + return re instanceof RegExp || // easy case + // duck-type for context-switching evalcx case + typeof(re) === 'function' && + re.constructor.name === 'RegExp' && + re.compile && + re.test && + re.exec && + s.match(/^\/.*\/[gim]{0,3}$/); + }; + + function isDate(d) { + if (d instanceof Date) return true; + return false; + }; + + function keys (obj) { + if (Object.keys) { + return Object.keys(obj); + } + + var keys = []; + + for (var i in obj) { + if (Object.prototype.hasOwnProperty.call(obj, i)) { + keys.push(i); + } + } + + return keys; + } + + function map (arr, mapper, that) { + if (Array.prototype.map) { + return Array.prototype.map.call(arr, mapper, that); + } + + var other= new Array(arr.length); + + for (var i= 0, n = arr.length; i= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= len) + throw new TypeError(); + } while (true); + } + + for (; i < len; i++) { + if (i in this) + rv = fun.call(null, rv, this[i], i, this); + } + + return rv; + }; + + /** + * Asserts deep equality + * + * @see taken from node.js `assert` module (copyright Joyent, MIT license) + * @api private + */ + + expect.eql = function eql (actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if ('undefined' != typeof Buffer + && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } + } + + function isUndefinedOrNull (value) { + return value === null || value === undefined; + } + + function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; + } + + function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return expect.eql(a, b); + } + try{ + var ka = keys(a), + kb = keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!expect.eql(a[key], b[key])) + return false; + } + return true; + } + + var json = (function () { + "use strict"; + + if ('object' == typeof JSON && JSON.parse && JSON.stringify) { + return { + parse: nativeJSON.parse + , stringify: nativeJSON.stringify + } + } + + var JSON = {}; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + function date(d, key) { + return isFinite(d.valueOf()) ? + d.getUTCFullYear() + '-' + + f(d.getUTCMonth() + 1) + '-' + + f(d.getUTCDate()) + 'T' + + f(d.getUTCHours()) + ':' + + f(d.getUTCMinutes()) + ':' + + f(d.getUTCSeconds()) + 'Z' : null; + }; + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + + // Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + + if (value instanceof Date) { + value = date(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + + // JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + + return String(value); + + // If the type is 'object', we might be dealing with an object or an array or + // null. + + case 'object': + + // Due to a specification blunder in ECMAScript, typeof null is 'object', + // so watch out for that case. + + if (!value) { + return 'null'; + } + + // Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + + // Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + + // The value is an array. Stringify every element. Use null as a placeholder + // for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + + // Join all of the elements together, separated with commas, and wrap them in + // brackets. + + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + + // Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + + // If the JSON object does not yet have a stringify method, give it one. + + JSON.stringify = function (value, replacer, space) { + + // The stringify method takes a value and an optional replacer, and an optional + // space parameter, and returns a JSON text. The replacer can be a function + // that can replace values, or an array of strings that will select the keys. + // A default replacer method can be provided. Use of the space parameter can + // produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + + // If the space parameter is a number, make an indent string containing that + // many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + + // If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + + // Make a fake root object containing our value under the key of ''. + // Return the result of stringifying the value. + + return str('', {'': value}); + }; + + // If the JSON object does not yet have a parse method, give it one. + + JSON.parse = function (text, reviver) { + // The parse method takes a text and an optional reviver function, and returns + // a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + + // The walk method is used to recursively walk the resulting structure so + // that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + + // Parsing happens in four stages. In the first stage, we replace certain + // Unicode characters with escape sequences. JavaScript handles many characters + // incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + + // In the second stage, we run the text against regular expressions that look + // for non-JSON patterns. We are especially concerned with '()' and 'new' + // because they can cause invocation, and '=' because it can cause mutation. + // But just to be safe, we want to reject all unexpected forms. + + // We split the second stage into 4 regexp operations in order to work around + // crippling inefficiencies in IE's and Safari's regexp engines. First we + // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we + // replace all simple value tokens with ']' characters. Third, we delete all + // open brackets that follow a colon or comma or that begin the text. Finally, + // we look to see that the remaining characters are only whitespace or ']' or + // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + + // In the third stage we use the eval function to compile the text into a + // JavaScript structure. The '{' operator is subject to a syntactic ambiguity + // in JavaScript: it can begin a block or an object literal. We wrap the text + // in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + + // In the optional fourth stage, we recursively walk the new structure, passing + // each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + + // If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + + return JSON; + })(); + + if ('undefined' != typeof window) { + window.expect = module.exports; + } + +})( + this + , 'undefined' != typeof module ? module : {} + , 'undefined' != typeof exports ? exports : {} +); \ No newline at end of file diff --git a/node_modules/express/node_modules/connect/node_modules/qs/test/browser/index.html b/node_modules/express/node_modules/connect/node_modules/qs/test/browser/index.html new file mode 100644 index 0000000..c73147a --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/test/browser/index.html @@ -0,0 +1,18 @@ + + + Mocha + + + + + + + + + + + + +
    + + diff --git a/node_modules/express/node_modules/connect/node_modules/qs/test/browser/jquery.js b/node_modules/express/node_modules/connect/node_modules/qs/test/browser/jquery.js new file mode 100644 index 0000000..f3201aa --- /dev/null +++ b/node_modules/express/node_modules/connect/node_modules/qs/test/browser/jquery.js @@ -0,0 +1,8981 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z])/ig, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Converts a dashed string to camelCased string; + // Used by both the css and data modules + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action ]( returned ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
    a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0 + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: -1000, + top: -1000 + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? + // Check for both converted-to-camel and non-converted data property names + thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] : + thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + rinvalidChar = /\:|^on/, + formHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + + hooks = boolHook; + + // Use formHook for forms and if the name contains certain characters + } else if ( formHook && name !== "className" && + (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { + + hooks = formHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + }, + // Use the value property for back compat + // Use the formHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: {} +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + return jQuery.prop( elem, name ) ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // propFix is more comprehensive and contains all fixes + jQuery.attrFix = jQuery.propFix; + + // Use this for any attribute on a form in IE6/7 + formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + + + + diff --git a/node_modules/express/node_modules/debug/example/wildcards.js b/node_modules/express/node_modules/debug/example/wildcards.js new file mode 100644 index 0000000..1fdac20 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/wildcards.js @@ -0,0 +1,10 @@ + +var debug = { + foo: require('../')('test:foo'), + bar: require('../')('test:bar'), + baz: require('../')('test:baz') +}; + +debug.foo('foo') +debug.bar('bar') +debug.baz('baz') \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/example/worker.js b/node_modules/express/node_modules/debug/example/worker.js new file mode 100644 index 0000000..7f6d288 --- /dev/null +++ b/node_modules/express/node_modules/debug/example/worker.js @@ -0,0 +1,22 @@ + +// DEBUG=* node example/worker +// DEBUG=worker:* node example/worker +// DEBUG=worker:a node example/worker +// DEBUG=worker:b node example/worker + +var a = require('../')('worker:a') + , b = require('../')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/head.js b/node_modules/express/node_modules/debug/head.js new file mode 100644 index 0000000..55d3817 --- /dev/null +++ b/node_modules/express/node_modules/debug/head.js @@ -0,0 +1 @@ +;(function(){ diff --git a/node_modules/express/node_modules/debug/index.js b/node_modules/express/node_modules/debug/index.js new file mode 100644 index 0000000..ee54454 --- /dev/null +++ b/node_modules/express/node_modules/debug/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/debug'); \ No newline at end of file diff --git a/node_modules/express/node_modules/debug/lib/debug.js b/node_modules/express/node_modules/debug/lib/debug.js new file mode 100644 index 0000000..969d122 --- /dev/null +++ b/node_modules/express/node_modules/debug/lib/debug.js @@ -0,0 +1,135 @@ + +/** + * Module dependencies. + */ + +var tty = require('tty'); + +/** + * Expose `debug()` as the module. + */ + +module.exports = debug; + +/** + * Enabled debuggers. + */ + +var names = [] + , skips = []; + +(process.env.DEBUG || '') + .split(/[\s,]+/) + .forEach(function(name){ + name = name.replace('*', '.*?'); + if (name[0] === '-') { + skips.push(new RegExp('^' + name.substr(1) + '$')); + } else { + names.push(new RegExp('^' + name + '$')); + } + }); + +/** + * Colors. + */ + +var colors = [6, 2, 3, 4, 5, 1]; + +/** + * Previous debug() call. + */ + +var prev = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Is stdout a TTY? Colored output is disabled when `true`. + */ + +var isatty = tty.isatty(2); + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function color() { + return colors[prevColor++ % colors.length]; +} + +/** + * Humanize the given `ms`. + * + * @param {Number} m + * @return {String} + * @api private + */ + +function humanize(ms) { + var sec = 1000 + , min = 60 * 1000 + , hour = 60 * min; + + if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; + if (ms >= min) return (ms / min).toFixed(1) + 'm'; + if (ms >= sec) return (ms / sec | 0) + 's'; + return ms + 'ms'; +} + +/** + * Create a debugger with the given `name`. + * + * @param {String} name + * @return {Type} + * @api public + */ + +function debug(name) { + function disabled(){} + disabled.enabled = false; + + var match = skips.some(function(re){ + return re.test(name); + }); + + if (match) return disabled; + + match = names.some(function(re){ + return re.test(name); + }); + + if (!match) return disabled; + var c = color(); + + function colored(fmt) { + var curr = new Date; + var ms = curr - (prev[name] || curr); + prev[name] = curr; + + fmt = ' \033[9' + c + 'm' + name + ' ' + + '\033[3' + c + 'm\033[90m' + + fmt + '\033[3' + c + 'm' + + ' +' + humanize(ms) + '\033[0m'; + + console.error.apply(this, arguments); + } + + function plain(fmt) { + fmt = new Date().toUTCString() + + ' ' + name + ' ' + fmt; + console.error.apply(this, arguments); + } + + colored.enabled = plain.enabled = true; + + return isatty + ? colored + : plain; +} diff --git a/node_modules/express/node_modules/debug/package.json b/node_modules/express/node_modules/debug/package.json new file mode 100644 index 0000000..3906600 --- /dev/null +++ b/node_modules/express/node_modules/debug/package.json @@ -0,0 +1,31 @@ +{ + "name": "debug", + "version": "0.7.0", + "description": "small debugging utility", + "keywords": [ + "debug", + "log", + "debugger" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*" + }, + "main": "index", + "browserify": "debug.component.js", + "engines": { + "node": "*" + }, + "component": { + "scripts": { + "debug": "debug.component.js" + } + }, + "readme": "\n# debug\n\n tiny node.js debugging utility.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Example\n\n This module is modelled after node core's debugging technique, allowing you to enable one or more topic-specific debugging functions, for example core does the following within many modules:\n\n```js\nvar debug;\nif (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) {\n debug = function(x) {\n var prefix = process.pid + ',' +\n (process.env.NODE_WORKER_ID ? 'Worker' : 'Master');\n console.error(prefix, x);\n };\n} else {\n debug = function() { };\n}\n```\n\n This concept is extremely simple but it works well. With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "_id": "debug@0.7.0", + "_from": "debug@*" +} diff --git a/node_modules/express/node_modules/debug/tail.js b/node_modules/express/node_modules/debug/tail.js new file mode 100644 index 0000000..5bf3fd3 --- /dev/null +++ b/node_modules/express/node_modules/debug/tail.js @@ -0,0 +1,4 @@ + + module.exports = debug; + +})(); \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/.npmignore b/node_modules/express/node_modules/fresh/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/fresh/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/fresh/Makefile b/node_modules/express/node_modules/fresh/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/fresh/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/Readme.md b/node_modules/express/node_modules/fresh/Readme.md new file mode 100644 index 0000000..273130d --- /dev/null +++ b/node_modules/express/node_modules/fresh/Readme.md @@ -0,0 +1,32 @@ + +# node-fresh + + HTTP response freshness testing + +## fresh(req, res) + + Check freshness of `req` and `res` headers. + + When the cache is "fresh" __true__ is returned, + otherwise __false__ is returned to indicate that + the cache is now stale. + +## Example: + +```js +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'luna' }; +fresh(req, res); +// => false + +var req = { 'if-none-match': 'tobi' }; +var res = { 'etag': 'tobi' }; +fresh(req, res); +// => true +``` + +## Installation + +``` +$ npm install fresh +``` \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/index.js b/node_modules/express/node_modules/fresh/index.js new file mode 100644 index 0000000..b2f4d41 --- /dev/null +++ b/node_modules/express/node_modules/fresh/index.js @@ -0,0 +1,49 @@ + +/** + * Expose `fresh()`. + */ + +module.exports = fresh; + +/** + * Check freshness of `req` and `res` headers. + * + * When the cache is "fresh" __true__ is returned, + * otherwise __false__ is returned to indicate that + * the cache is now stale. + * + * @param {Object} req + * @param {Object} res + * @return {Boolean} + * @api public + */ + +function fresh(req, res) { + // defaults + var etagMatches = true; + var notModified = true; + + // fields + var modifiedSince = req['if-modified-since']; + var noneMatch = req['if-none-match']; + var lastModified = res['last-modified']; + var etag = res['etag']; + + // unconditional request + if (!modifiedSince && !noneMatch) return false; + + // parse if-none-match + if (noneMatch) noneMatch = noneMatch.split(/ *, */); + + // if-none-match + if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0]; + + // if-modified-since + if (modifiedSince) { + modifiedSince = new Date(modifiedSince); + lastModified = new Date(lastModified); + notModified = lastModified <= modifiedSince; + } + + return !! (etagMatches && notModified); +} \ No newline at end of file diff --git a/node_modules/express/node_modules/fresh/package.json b/node_modules/express/node_modules/fresh/package.json new file mode 100644 index 0000000..e1f985e --- /dev/null +++ b/node_modules/express/node_modules/fresh/package.json @@ -0,0 +1,19 @@ +{ + "name": "fresh", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "HTTP response freshness testing", + "version": "0.1.0", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "\n# node-fresh\n\n HTTP response freshness testing\n\n## fresh(req, res)\n\n Check freshness of `req` and `res` headers.\n\n When the cache is \"fresh\" __true__ is returned,\n otherwise __false__ is returned to indicate that\n the cache is now stale.\n\n## Example:\n\n```js\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'luna' };\nfresh(req, res);\n// => false\n\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'tobi' };\nfresh(req, res);\n// => true\n```\n\n## Installation\n\n```\n$ npm install fresh\n```", + "_id": "fresh@0.1.0", + "_from": "fresh@0.1.0" +} diff --git a/node_modules/express/node_modules/methods/index.js b/node_modules/express/node_modules/methods/index.js new file mode 100644 index 0000000..297d022 --- /dev/null +++ b/node_modules/express/node_modules/methods/index.js @@ -0,0 +1,26 @@ + +module.exports = [ + 'get' + , 'post' + , 'put' + , 'head' + , 'delete' + , 'options' + , 'trace' + , 'copy' + , 'lock' + , 'mkcol' + , 'move' + , 'propfind' + , 'proppatch' + , 'unlock' + , 'report' + , 'mkactivity' + , 'checkout' + , 'merge' + , 'm-search' + , 'notify' + , 'subscribe' + , 'unsubscribe' + , 'patch' +]; \ No newline at end of file diff --git a/node_modules/express/node_modules/methods/package.json b/node_modules/express/node_modules/methods/package.json new file mode 100644 index 0000000..341b226 --- /dev/null +++ b/node_modules/express/node_modules/methods/package.json @@ -0,0 +1,20 @@ +{ + "name": "methods", + "version": "0.0.1", + "description": "HTTP methods that node supports", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "http", + "methods" + ], + "author": { + "name": "TJ Holowaychuk" + }, + "license": "MIT", + "_id": "methods@0.0.1", + "readme": "ERROR: No README.md file found!", + "_from": "methods@0.0.1" +} diff --git a/node_modules/express/node_modules/mkdirp/.gitignore.orig b/node_modules/express/node_modules/mkdirp/.gitignore.orig new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.gitignore.orig @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/express/node_modules/mkdirp/.gitignore.rej b/node_modules/express/node_modules/mkdirp/.gitignore.rej new file mode 100644 index 0000000..69244ff --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.gitignore.rej @@ -0,0 +1,5 @@ +--- /dev/null ++++ .gitignore +@@ -0,0 +1,2 @@ ++node_modules/ ++npm-debug.log \ No newline at end of file diff --git a/node_modules/express/node_modules/mkdirp/.npmignore b/node_modules/express/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/express/node_modules/mkdirp/.travis.yml b/node_modules/express/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/express/node_modules/mkdirp/LICENSE b/node_modules/express/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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. diff --git a/node_modules/express/node_modules/mkdirp/README.markdown b/node_modules/express/node_modules/mkdirp/README.markdown new file mode 100644 index 0000000..40de04f --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/README.markdown @@ -0,0 +1,61 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js b/node_modules/express/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js.orig b/node_modules/express/node_modules/mkdirp/examples/pow.js.orig new file mode 100644 index 0000000..7741462 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/examples/pow.js.orig @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js.rej b/node_modules/express/node_modules/mkdirp/examples/pow.js.rej new file mode 100644 index 0000000..81e7f43 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/examples/pow.js.rej @@ -0,0 +1,19 @@ +--- examples/pow.js ++++ examples/pow.js +@@ -1,6 +1,15 @@ +-var mkdirp = require('mkdirp').mkdirp; ++var mkdirp = require('../').mkdirp, ++ mkdirpSync = require('../').mkdirpSync; + + mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') + }); ++ ++try { ++ mkdirpSync('/tmp/bar/foo/baz', 0755); ++ console.log('double pow!'); ++} ++catch (ex) { ++ console.log(ex); ++} \ No newline at end of file diff --git a/node_modules/express/node_modules/mkdirp/index.js b/node_modules/express/node_modules/mkdirp/index.js new file mode 100644 index 0000000..874b310 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/index.js @@ -0,0 +1,94 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + case 'EISDIR': + case 'EPERM': + // Operation not permitted or already is a dir. + // This is the error you get when trying to mkdir('c:/') + // on windows, or mkdir('/') on unix. Make sure it's a + // dir by falling through to the EEXIST case. + case 'EROFS': + // a read-only file system. + // However, the dir could already exist, in which case + // the EROFS error will be obscuring a EEXIST! + // Fallthrough to that case. + case 'EEXIST': + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + + default: + cb(er, made); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + case 'EEXIST' : + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + default : + throw err0 + break; + } + } + + return made; +}; diff --git a/node_modules/express/node_modules/mkdirp/package.json b/node_modules/express/node_modules/mkdirp/package.json new file mode 100644 index 0000000..b5a2c99 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/package.json @@ -0,0 +1,32 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.3", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.2.4" + }, + "license": "MIT/X11", + "engines": { + "node": "*" + }, + "readme": "mkdirp\n======\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\nexample\n=======\n\npow.js\n------\n var mkdirp = require('mkdirp');\n \n mkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n });\n\nOutput\n pow!\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\nmethods\n=======\n\nvar mkdirp = require('mkdirp');\n\nmkdirp(dir, mode, cb)\n---------------------\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nmkdirp.sync(dir, mode)\n----------------------\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n npm install mkdirp\n\nlicense\n=======\n\nMIT/X11\n", + "_id": "mkdirp@0.3.3", + "_from": "mkdirp@0.3.3" +} diff --git a/node_modules/express/node_modules/mkdirp/test/chmod.js b/node_modules/express/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/clobber.js b/node_modules/express/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/mkdirp.js b/node_modules/express/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/perm.js b/node_modules/express/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/perm_sync.js b/node_modules/express/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/race.js b/node_modules/express/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/express/node_modules/mkdirp/test/rel.js b/node_modules/express/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/return.js b/node_modules/express/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/return_sync.js b/node_modules/express/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/root.js b/node_modules/express/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/sync.js b/node_modules/express/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/umask.js b/node_modules/express/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/express/node_modules/mkdirp/test/umask_sync.js b/node_modules/express/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/express/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/express/node_modules/range-parser/.npmignore b/node_modules/express/node_modules/range-parser/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/express/node_modules/range-parser/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/express/node_modules/range-parser/History.md b/node_modules/express/node_modules/range-parser/History.md new file mode 100644 index 0000000..82df7b1 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/History.md @@ -0,0 +1,15 @@ + +0.0.4 / 2012-06-17 +================== + + * changed: ret -1 for unsatisfiable and -2 when invalid + +0.0.3 / 2012-06-17 +================== + + * fix last-byte-pos default to len - 1 + +0.0.2 / 2012-06-14 +================== + + * add `.type` diff --git a/node_modules/express/node_modules/range-parser/Makefile b/node_modules/express/node_modules/range-parser/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/express/node_modules/range-parser/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/Readme.md b/node_modules/express/node_modules/range-parser/Readme.md new file mode 100644 index 0000000..b2a67fe --- /dev/null +++ b/node_modules/express/node_modules/range-parser/Readme.md @@ -0,0 +1,28 @@ + +# node-range-parser + + Range header field parser. + +## Example: + +```js +assert(-1 == parse(200, 'bytes=500-20')); +assert(-2 == parse(200, 'bytes=malformed')); +parse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }])); +parse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }])); +parse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }])); +parse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }])); +parse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }])); +parse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }])); +parse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }])); +parse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }])); +parse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }])); +parse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }])); +parse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }])); +``` + +## Installation + +``` +$ npm install range-parser +``` \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/index.js b/node_modules/express/node_modules/range-parser/index.js new file mode 100644 index 0000000..9b0f7a8 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/index.js @@ -0,0 +1,49 @@ + +/** + * Parse "Range" header `str` relative to the given file `size`. + * + * @param {Number} size + * @param {String} str + * @return {Array} + * @api public + */ + +module.exports = function(size, str){ + var valid = true; + var i = str.indexOf('='); + + if (-1 == i) return -2; + + var arr = str.slice(i + 1).split(',').map(function(range){ + var range = range.split('-') + , start = parseInt(range[0], 10) + , end = parseInt(range[1], 10); + + // -nnn + if (isNaN(start)) { + start = size - end; + end = size - 1; + // nnn- + } else if (isNaN(end)) { + end = size - 1; + } + + // limit last-byte-pos to current length + if (end > size - 1) end = size - 1; + + // invalid + if (isNaN(start) + || isNaN(end) + || start > end + || start < 0) valid = false; + + return { + start: start, + end: end + }; + }); + + arr.type = str.slice(0, i); + + return valid ? arr : -1; +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/range-parser/package.json b/node_modules/express/node_modules/range-parser/package.json new file mode 100644 index 0000000..8ff3a32 --- /dev/null +++ b/node_modules/express/node_modules/range-parser/package.json @@ -0,0 +1,19 @@ +{ + "name": "range-parser", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "description": "Range header field string parser", + "version": "0.0.4", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "readme": "\n# node-range-parser\n\n Range header field parser.\n\n## Example:\n\n```js\nassert(-1 == parse(200, 'bytes=500-20'));\nassert(-2 == parse(200, 'bytes=malformed'));\nparse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));\nparse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));\nparse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));\nparse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));\nparse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));\nparse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));\nparse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));\nparse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));\nparse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));\n```\n\n## Installation\n\n```\n$ npm install range-parser\n```", + "_id": "range-parser@0.0.4", + "_from": "range-parser@0.0.4" +} diff --git a/node_modules/express/node_modules/send/.npmignore b/node_modules/express/node_modules/send/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/express/node_modules/send/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/express/node_modules/send/History.md b/node_modules/express/node_modules/send/History.md new file mode 100644 index 0000000..20c5319 --- /dev/null +++ b/node_modules/express/node_modules/send/History.md @@ -0,0 +1,25 @@ + +0.1.0 / 2012-08-25 +================== + + * add options parameter to send() that is passed to fs.createReadStream() [kanongil] + +0.0.4 / 2012-08-16 +================== + + * allow custom "Accept-Ranges" definition + +0.0.3 / 2012-07-16 +================== + + * fix normalization of the root directory. Closes #3 + +0.0.2 / 2012-07-09 +================== + + * add passing of req explicitly for now (YUCK) + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/express/node_modules/send/Makefile b/node_modules/express/node_modules/send/Makefile new file mode 100644 index 0000000..a9dcfd5 --- /dev/null +++ b/node_modules/express/node_modules/send/Makefile @@ -0,0 +1,8 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec \ + --bail + +.PHONY: test \ No newline at end of file diff --git a/node_modules/express/node_modules/send/Readme.md b/node_modules/express/node_modules/send/Readme.md new file mode 100644 index 0000000..85171a9 --- /dev/null +++ b/node_modules/express/node_modules/send/Readme.md @@ -0,0 +1,123 @@ + +# send + + Send is Connect's `static()` extracted for generalized use, a streaming static file + server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework. + +## Installation + + $ npm install send + +## Examples + + Small: + +```js +var http = require('http'); +var send = require('send'); + +var app = http.createServer(function(req, res){ + send(req, req.url).pipe(res); +}); +``` + + Serving from a root directory with custom error-handling: + +```js +var http = require('http'); +var send = require('send'); + +var app = http.createServer(function(req, res){ + // your custom error-handling logic: + function error(err) { + res.statusCode = err.status || 500; + res.end(err.message); + } + + // your custom directory handling logic: + function redirect() { + res.statusCode = 301; + res.setHeader('Location', req.url + '/'); + res.end('Redirecting to ' + req.url + '/'); + } + + // transfer arbitrary files from within + // /www/example.com/public/* + send(req, url.parse(req.url).pathname) + .root('/www/example.com/public') + .on('error', error) + .on('directory', redirect) + .pipe(res); +}); +``` + +## API + +### Events + + - `error` an error occurred `(err)` + - `directory` a directory was requested + - `stream` file streaming has started `(stream)` + - `end` streaming has completed + +### .root(dir) + + Serve files relative to `path`. Aliased as `.from(dir)`. + +### .index(path) + + By default send supports "index.html" files, to disable this + invoke `.index(false)` or to supply a new index pass a string. + +### .maxage(ms) + + Provide a max-age in milliseconds for http caching, defaults to 0. + +## Error-handling + + By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc. + +## Caching + + It does _not_ perform internal caching, you should use a reverse proxy cache such + as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;). + +## Debugging + + To enable `debug()` instrumentation output export __DEBUG__: + +``` +$ DEBUG=send node app +``` + +## Running tests + +``` +$ npm install +$ make test +``` + +## License + +(The MIT License) + +Copyright (c) 2012 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. \ No newline at end of file diff --git a/node_modules/express/node_modules/send/index.js b/node_modules/express/node_modules/send/index.js new file mode 100644 index 0000000..f17158d --- /dev/null +++ b/node_modules/express/node_modules/send/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/send'); \ No newline at end of file diff --git a/node_modules/express/node_modules/send/lib/send.js b/node_modules/express/node_modules/send/lib/send.js new file mode 100644 index 0000000..de72146 --- /dev/null +++ b/node_modules/express/node_modules/send/lib/send.js @@ -0,0 +1,473 @@ + +/** + * Module dependencies. + */ + +var debug = require('debug')('send') + , parseRange = require('range-parser') + , Stream = require('stream') + , mime = require('mime') + , fresh = require('fresh') + , path = require('path') + , http = require('http') + , fs = require('fs') + , basename = path.basename + , normalize = path.normalize + , join = path.join + , utils = require('./utils'); + +/** + * Expose `send`. + */ + +exports = module.exports = send; + +/** + * Expose mime module. + */ + +exports.mime = mime; + +/** + * Return a `SendStream` for `req` and `path`. + * + * @param {Request} req + * @param {String} path + * @param {Object} options + * @return {SendStream} + * @api public + */ + +function send(req, path, options) { + return new SendStream(req, path, options); +} + +/** + * Initialize a `SendStream` with the given `path`. + * + * Events: + * + * - `error` an error occurred + * - `stream` file streaming has started + * - `end` streaming has completed + * - `directory` a directory was requested + * + * @param {Request} req + * @param {String} path + * @param {Object} options + * @api private + */ + +function SendStream(req, path, options) { + var self = this; + this.req = req; + this.path = path; + this.options = options || {}; + this.maxage(0); + this.hidden(false); + this.index('index.html'); +} + +/** + * Inherits from `Stream.prototype`. + */ + +SendStream.prototype.__proto__ = Stream.prototype; + +/** + * Enable or disable "hidden" (dot) files. + * + * @param {Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.hidden = function(val){ + debug('hidden %s', val); + this._hidden = val; + return this; +}; + +/** + * Set index `path`, set to a falsy + * value to disable index support. + * + * @param {String|Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.index = function(path){ + debug('index %s', path); + this._index = path; + return this; +}; + +/** + * Set root `path`. + * + * @param {String} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.root = +SendStream.prototype.from = function(path){ + this._root = normalize(path); + return this; +}; + +/** + * Set max-age to `ms`. + * + * @param {Number} ms + * @return {SendStream} + * @api public + */ + +SendStream.prototype.maxage = function(ms){ + if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000; + debug('max-age %d', ms); + this._maxage = ms; + return this; +}; + +/** + * Emit error with `status`. + * + * @param {Number} status + * @api private + */ + +SendStream.prototype.error = function(status, err){ + var res = this.res; + var msg = http.STATUS_CODES[status]; + err = err || new Error(msg); + err.status = status; + if (this.listeners('error').length) return this.emit('error', err); + res.statusCode = err.status; + res.end(msg); +}; + +/** + * Check if the pathname is potentially malicious. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isMalicious = function(){ + return !this._root && ~this.path.indexOf('..'); +}; + +/** + * Check if the pathname ends with "/". + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.hasTrailingSlash = function(){ + return '/' == this.path[this.path.length - 1]; +}; + +/** + * Check if the basename leads with ".". + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.hasLeadingDot = function(){ + return '.' == basename(this.path)[0]; +}; + +/** + * Check if this is a conditional GET request. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isConditionalGET = function(){ + return this.req.headers['if-none-match'] + || this.req.headers['if-modified-since']; +}; + +/** + * Strip content-* header fields. + * + * @api private + */ + +SendStream.prototype.removeContentHeaderFields = function(){ + var res = this.res; + Object.keys(res._headers).forEach(function(field){ + if (0 == field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Respond with 304 not modified. + * + * @api private + */ + +SendStream.prototype.notModified = function(){ + var res = this.res; + debug('not modified'); + this.removeContentHeaderFields(); + res.statusCode = 304; + res.end(); +}; + +/** + * Check if the request is cacheable, aka + * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}). + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isCachable = function(){ + var res = this.res; + return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode; +}; + +/** + * Handle stat() error. + * + * @param {Error} err + * @api private + */ + +SendStream.prototype.onStatError = function(err){ + var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR']; + if (~notfound.indexOf(err.code)) return this.error(404, err); + this.error(500, err); +}; + +/** + * Check if the cache is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isFresh = function(){ + return fresh(this.req.headers, this.res._headers); +}; + +/** + * Redirect to `path`. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.redirect = function(path){ + if (this.listeners('directory').length) return this.emit('directory'); + var res = this.res; + path += '/'; + res.statusCode = 301; + res.setHeader('Location', path); + res.end('Redirecting to ' + utils.escape(path)); +}; + +/** + * Pipe to `res. + * + * @param {Stream} res + * @return {Stream} res + * @api public + */ + +SendStream.prototype.pipe = function(res){ + var self = this + , args = arguments + , path = this.path + , root = this._root; + + // references + this.res = res; + + // invalid request uri + path = utils.decode(path); + if (-1 == path) return this.error(400); + + // null byte(s) + if (~path.indexOf('\0')) return this.error(400); + + // join / normalize from optional root dir + if (root) path = normalize(join(this._root, path)); + + // ".." is malicious without "root" + if (this.isMalicious()) return this.error(403); + + // malicious path + if (root && 0 != path.indexOf(root)) return this.error(403); + + // hidden file support + if (!this._hidden && this.hasLeadingDot()) return this.error(404); + + // index file support + if (this._index && this.hasTrailingSlash()) path += this._index; + + debug('stat "%s"', path); + fs.stat(path, function(err, stat){ + if (err) return self.onStatError(err); + if (stat.isDirectory()) return self.redirect(self.path); + self.send(path, stat); + }); + + return res; +}; + +/** + * Transfer `path`. + * + * @param {String} path + * @api public + */ + +SendStream.prototype.send = function(path, stat){ + var options = this.options; + var len = stat.size; + var res = this.res; + var req = this.req; + var ranges = req.headers.range; + var offset = options.start || 0; + + // set header fields + this.setHeader(stat); + + // set content-type + this.type(path); + + // conditional GET support + if (this.isConditionalGET() + && this.isCachable() + && this.isFresh()) { + return this.notModified(); + } + + // adjust len to start/end options + len = Math.max(0, len - offset); + if (options.end !== undefined) { + var bytes = options.end - offset + 1; + if (len > bytes) len = bytes; + } + + // Range support + if (ranges) { + ranges = parseRange(len, ranges); + + // unsatisfiable + if (-1 == ranges) { + res.setHeader('Content-Range', 'bytes */' + stat.size); + return this.error(416); + } + + // valid (syntactically invalid ranges are treated as a regular response) + if (-2 != ranges) { + options.start = offset + ranges[0].start; + options.end = offset + ranges[0].end; + + // Content-Range + res.statusCode = 206; + res.setHeader('Content-Range', 'bytes ' + + ranges[0].start + + '-' + + ranges[0].end + + '/' + + len); + len = options.end - options.start + 1; + } + } + + // content-length + res.setHeader('Content-Length', len); + + // HEAD support + if ('HEAD' == req.method) return res.end(); + + this.stream(path, options); +}; + +/** + * Stream `path` to the response. + * + * @param {String} path + * @param {Object} options + * @api private + */ + +SendStream.prototype.stream = function(path, options){ + // TODO: this is all lame, refactor meeee + var self = this; + var res = this.res; + var req = this.req; + + // pipe + var stream = fs.createReadStream(path, options); + this.emit('stream', stream); + stream.pipe(res); + + // socket closed, done with the fd + req.on('close', stream.destroy.bind(stream)); + + // error handling code-smell + stream.on('error', function(err){ + // no hope in responding + if (res._header) { + console.error(err.stack); + req.destroy(); + return; + } + + // 500 + err.status = 500; + self.emit('error', err); + }); + + // end + stream.on('end', function(){ + self.emit('end'); + }); +}; + +/** + * Set content-type based on `path` + * if it hasn't been explicitly set. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.type = function(path){ + var res = this.res; + if (res.getHeader('Content-Type')) return; + var type = mime.lookup(path); + var charset = mime.charsets.lookup(type); + debug('content-type %s', type); + res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : '')); +}; + +/** + * Set reaponse header fields, most + * fields may be pre-defined. + * + * @param {Object} stat + * @api private + */ + +SendStream.prototype.setHeader = function(stat){ + var res = this.res; + if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes'); + if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat)); + if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString()); + if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000)); + if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString()); +}; diff --git a/node_modules/express/node_modules/send/lib/utils.js b/node_modules/express/node_modules/send/lib/utils.js new file mode 100644 index 0000000..950e5a2 --- /dev/null +++ b/node_modules/express/node_modules/send/lib/utils.js @@ -0,0 +1,47 @@ + +/** + * Return an ETag in the form of `"-"` + * from the given `stat`. + * + * @param {Object} stat + * @return {String} + * @api private + */ + +exports.etag = function(stat) { + return '"' + stat.size + '-' + Number(stat.mtime) + '"'; +}; + +/** + * decodeURIComponent. + * + * Allows V8 to only deoptimize this fn instead of all + * of send(). + * + * @param {String} path + * @api private + */ + +exports.decode = function(path){ + try { + return decodeURIComponent(path); + } catch (err) { + return -1; + } +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; \ No newline at end of file diff --git a/node_modules/express/node_modules/send/node_modules/mime/LICENSE b/node_modules/express/node_modules/send/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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. diff --git a/node_modules/express/node_modules/send/node_modules/mime/README.md b/node_modules/express/node_modules/send/node_modules/mime/README.md new file mode 100644 index 0000000..d8b66a8 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/README.md @@ -0,0 +1,63 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/express/node_modules/send/node_modules/mime/mime.js b/node_modules/express/node_modules/send/node_modules/mime/mime.js new file mode 100644 index 0000000..1e00585 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/mime.js @@ -0,0 +1,104 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + return this.extensions[mimeType]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +} + +module.exports = mime; diff --git a/node_modules/express/node_modules/send/node_modules/mime/package.json b/node_modules/express/node_modules/send/node_modules/mime/package.json new file mode 100644 index 0000000..a265300 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/package.json @@ -0,0 +1,31 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "https://github.com/broofa/node-mime", + "type": "git" + }, + "version": "1.2.6", + "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g.\n\n var mime = require('mime');\n\n mime.lookup('/path/to/file.txt'); // => 'text/plain'\n mime.lookup('file.txt'); // => 'text/plain'\n mime.lookup('.TXT'); // => 'text/plain'\n mime.lookup('htm'); // => 'text/html'\n\n### mime.extension(type)\nGet the default extension for `type`\n\n mime.extension('text/html'); // => 'html'\n mime.extension('application/octet-stream'); // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n mime.charsets.lookup('text/plain'); // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n mime.define({\n 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n 'application/x-my-type': ['x-mt', 'x-mtt'],\n // etc ...\n });\n\n mime.lookup('x-sft'); // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n mime.load('./my_project.types');\n\nThe .types file format is simple - See the `types` dir for examples.\n", + "_id": "mime@1.2.6", + "_from": "mime@1.2.6" +} diff --git a/node_modules/express/node_modules/send/node_modules/mime/test.js b/node_modules/express/node_modules/send/node_modules/mime/test.js new file mode 100644 index 0000000..cbad034 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/test.js @@ -0,0 +1,55 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); +eq('text/plain', mime.lookup('.text.txt')); +eq('text/plain', mime.lookup('.txt')); +eq('text/plain', mime.lookup('txt')); +eq('application/octet-stream', mime.lookup('text.nope')); +eq('fallback', mime.lookup('text.fallback', 'fallback')); +eq('application/octet-stream', mime.lookup('constructor')); +eq('text/plain', mime.lookup('TEXT.TXT')); +eq('text/event-stream', mime.lookup('text/event-stream')); +eq('application/x-web-app-manifest+json', mime.lookup('text.webapp')); + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq(undefined, mime.extension('constructor')); + +// +// Test node types +// + +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +console.log('\nOK'); diff --git a/node_modules/express/node_modules/send/node_modules/mime/types/mime.types b/node_modules/express/node_modules/send/node_modules/mime/types/mime.types new file mode 100644 index 0000000..b3cae2e --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/types/mime.types @@ -0,0 +1,1510 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file dvb +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/node_modules/express/node_modules/send/node_modules/mime/types/node.types b/node_modules/express/node_modules/send/node_modules/mime/types/node.types new file mode 100644 index 0000000..b7fe8c0 --- /dev/null +++ b/node_modules/express/node_modules/send/node_modules/mime/types/node.types @@ -0,0 +1,65 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: The FLAC lossless codec format +# Why: Streaming and serving FLAC audio +# Added by: jacobrask +audio/flac flac + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp + +# What: Matroska Mime Types +# Why: http://en.wikipedia.org/wiki/Matroska +# Added by: aduncan88 +video/x-matroska mkv +audio/x-matroska mka diff --git a/node_modules/express/node_modules/send/package.json b/node_modules/express/node_modules/send/package.json new file mode 100644 index 0000000..78fadcb --- /dev/null +++ b/node_modules/express/node_modules/send/package.json @@ -0,0 +1,33 @@ +{ + "name": "send", + "version": "0.1.0", + "description": "Better streaming static file server with Range and conditional-GET support", + "keywords": [ + "static", + "file", + "server" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": { + "debug": "*", + "mime": "1.2.6", + "fresh": "0.1.0", + "range-parser": "0.0.4" + }, + "devDependencies": { + "mocha": "*", + "should": "*", + "supertest": "0.0.1", + "connect": "2.x" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "readme": "\n# send\n\n Send is Connect's `static()` extracted for generalized use, a streaming static file\n server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.\n\n## Installation\n\n $ npm install send\n\n## Examples\n\n Small:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n send(req, req.url).pipe(res);\n});\n```\n\n Serving from a root directory with custom error-handling:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n // your custom error-handling logic:\n function error(err) {\n res.statusCode = err.status || 500;\n res.end(err.message);\n }\n\n // your custom directory handling logic:\n function redirect() {\n res.statusCode = 301;\n res.setHeader('Location', req.url + '/');\n res.end('Redirecting to ' + req.url + '/');\n }\n\n // transfer arbitrary files from within\n // /www/example.com/public/*\n send(req, url.parse(req.url).pathname)\n .root('/www/example.com/public')\n .on('error', error)\n .on('directory', redirect)\n .pipe(res);\n});\n```\n\n## API\n\n### Events\n\n - `error` an error occurred `(err)`\n - `directory` a directory was requested\n - `stream` file streaming has started `(stream)`\n - `end` streaming has completed\n\n### .root(dir)\n\n Serve files relative to `path`. Aliased as `.from(dir)`.\n\n### .index(path)\n\n By default send supports \"index.html\" files, to disable this\n invoke `.index(false)` or to supply a new index pass a string.\n\n### .maxage(ms)\n\n Provide a max-age in milliseconds for http caching, defaults to 0.\n\n## Error-handling\n\n By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.\n\n## Caching\n\n It does _not_ perform internal caching, you should use a reverse proxy cache such\n as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).\n\n## Debugging\n\n To enable `debug()` instrumentation output export __DEBUG__:\n\n```\n$ DEBUG=send node app\n```\n\n## Running tests\n\n```\n$ npm install\n$ make test\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "_id": "send@0.1.0", + "_from": "send@0.1.0" +} diff --git a/node_modules/express/package.json b/node_modules/express/package.json new file mode 100644 index 0000000..f0d0b7d --- /dev/null +++ b/node_modules/express/package.json @@ -0,0 +1,83 @@ +{ + "name": "express", + "description": "Sinatra inspired web development framework", + "version": "3.1.0", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "contributors": [ + { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "Aaron Heckmann", + "email": "aaron.heckmann+github@gmail.com" + }, + { + "name": "Ciaran Jessup", + "email": "ciaranj@gmail.com" + }, + { + "name": "Guillermo Rauch", + "email": "rauchg@gmail.com" + } + ], + "dependencies": { + "connect": "2.7.2", + "commander": "0.6.1", + "range-parser": "0.0.4", + "mkdirp": "0.3.3", + "cookie": "0.0.5", + "buffer-crc32": "0.1.1", + "fresh": "0.1.0", + "methods": "0.0.1", + "send": "0.1.0", + "cookie-signature": "0.0.1", + "debug": "*" + }, + "devDependencies": { + "ejs": "*", + "mocha": "*", + "jade": "*", + "hjs": "*", + "stylus": "*", + "should": "*", + "connect-redis": "*", + "github-flavored-markdown": "*", + "supertest": "0.0.1" + }, + "keywords": [ + "express", + "framework", + "sinatra", + "web", + "rest", + "restful", + "router", + "app", + "api" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/express" + }, + "main": "index", + "bin": { + "express": "./bin/express" + }, + "scripts": { + "prepublish": "npm prune", + "test": "make test" + }, + "engines": { + "node": "*" + }, + "readme": "![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)\n\n Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express)\n\n```js\nvar express = require('express');\nvar app = express();\n\napp.get('/', function(req, res){\n res.send('Hello World');\n});\n\napp.listen(3000);\n```\n\n## Installation\n\n $ npm install -g express\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:\n\n Create the app:\n\n $ npm install -g express\n $ express /tmp/foo && cd /tmp/foo\n\n Install dependencies:\n\n $ npm install\n\n Start the server:\n\n $ node app\n\n## Features\n\n * Built on [Connect](http://github.com/senchalabs/connect)\n * Robust routing\n * HTTP helpers (redirection, caching, etc)\n * View system supporting 14+ template engines\n * Content negotiation\n * Focus on high performance\n * Environment based configuration\n * Executable for generating applications quickly\n * High test coverage\n\n## Philosophy\n\n The Express philosophy is to provide small, robust tooling for HTTP servers. Making\n it a great solution for single page applications, web sites, hybrids, or public\n HTTP APIs.\n \n Built on Connect you can use _only_ what you need, and nothing more, applications\n can be as big or as small as you like, even a single file. Express does\n not force you to use any specific ORM or template engine. With support for over\n 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js)\n you can quickly craft your perfect framework.\n\n## More Information\n\n * Join #express on freenode\n * [Google Group](http://groups.google.com/group/express-js) for discussion\n * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates\n * Visit the [Wiki](http://github.com/visionmedia/express/wiki)\n * [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)\n * [Русскоязычная документация](http://express-js.ru/)\n\n## Viewing Examples\n\nClone the Express repo, then install the dev dependencies to install all the example / test suite deps:\n\n $ git clone git://github.com/visionmedia/express.git --depth 1\n $ cd express\n $ npm install\n\nthen run whichever tests you want:\n\n $ node examples/content-negotiation\n\n## Running Tests\n\nTo run the test suite first invoke the following command within the repo, installing the development dependencies:\n\n $ npm install\n\nthen run the tests:\n\n $ make test\n\n## Contributors\n\n```\nproject: express\ncommits: 3559\nactive : 468 days\nfiles : 237\nauthors: \n 1891\tTj Holowaychuk 53.1%\n 1285\tvisionmedia 36.1%\n 182\tTJ Holowaychuk 5.1%\n 54\tAaron Heckmann 1.5%\n 34\tcsausdev 1.0%\n 26\tciaranj 0.7%\n 21\tRobert Sköld 0.6%\n 6\tGuillermo Rauch 0.2%\n 3\tDav Glass 0.1%\n 3\tNick Poulden 0.1%\n 2\tRandy Merrill 0.1%\n 2\tBenny Wong 0.1%\n 2\tHunter Loftis 0.1%\n 2\tJake Gordon 0.1%\n 2\tBrian McKinney 0.1%\n 2\tRoman Shtylman 0.1%\n 2\tBen Weaver 0.1%\n 2\tDave Hoover 0.1%\n 2\tEivind Fjeldstad 0.1%\n 2\tDaniel Shaw 0.1%\n 1\tMatt Colyer 0.0%\n 1\tPau Ramon 0.0%\n 1\tPero Pejovic 0.0%\n 1\tPeter Rekdal Sunde 0.0%\n 1\tRaynos 0.0%\n 1\tTeng Siong Ong 0.0%\n 1\tViktor Kelemen 0.0%\n 1\tctide 0.0%\n 1\t8bitDesigner 0.0%\n 1\tisaacs 0.0%\n 1\tmgutz 0.0%\n 1\tpikeas 0.0%\n 1\tshuwatto 0.0%\n 1\ttstrimple 0.0%\n 1\tewoudj 0.0%\n 1\tAdam Sanderson 0.0%\n 1\tAndrii Kostenko 0.0%\n 1\tAndy Hiew 0.0%\n 1\tArpad Borsos 0.0%\n 1\tAshwin Purohit 0.0%\n 1\tBenjen 0.0%\n 1\tDarren Torpey 0.0%\n 1\tGreg Ritter 0.0%\n 1\tGregory Ritter 0.0%\n 1\tJames Herdman 0.0%\n 1\tJim Snodgrass 0.0%\n 1\tJoe McCann 0.0%\n 1\tJonathan Dumaine 0.0%\n 1\tJonathan Palardy 0.0%\n 1\tJonathan Zacsh 0.0%\n 1\tJustin Lilly 0.0%\n 1\tKen Sato 0.0%\n 1\tMaciej Małecki 0.0%\n 1\tMasahiro Hayashi 0.0%\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2009-2012 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "_id": "express@3.1.0", + "dist": { + "shasum": "f869b2d92320f5c3dd496c172e06f02b6ad43310" + }, + "_from": "express@3.1.0" +} diff --git a/node_modules/express/test.js b/node_modules/express/test.js new file mode 100644 index 0000000..112ee0a --- /dev/null +++ b/node_modules/express/test.js @@ -0,0 +1,14 @@ + +/** + * Module dependencies. + */ + +var express = require('./') + , app = express() + +app.get('/', function(req, res){ + console.log(req.query); +}); + +app.listen(3000); +console.log('listening on 3000'); diff --git a/node_modules/jade/.npmignore b/node_modules/jade/.npmignore new file mode 100644 index 0000000..fdc7b89 --- /dev/null +++ b/node_modules/jade/.npmignore @@ -0,0 +1,14 @@ +test +support +benchmarks +examples +lib-cov +coverage.html +.gitmodules +.travis.yml +History.md +Makefile +test/ +support/ +benchmarks/ +examples/ diff --git a/node_modules/jade/LICENSE b/node_modules/jade/LICENSE new file mode 100644 index 0000000..8ad0e0d --- /dev/null +++ b/node_modules/jade/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2009-2010 TJ Holowaychuk + +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. \ No newline at end of file diff --git a/node_modules/jade/Readme.md b/node_modules/jade/Readme.md new file mode 100644 index 0000000..9f629d9 --- /dev/null +++ b/node_modules/jade/Readme.md @@ -0,0 +1,1298 @@ + [![Build Status](https://secure.travis-ci.org/visionmedia/jade.png)](http://travis-ci.org/visionmedia/jade) + +# Jade - template engine + + Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com) + and implemented with JavaScript for [node](http://nodejs.org). For discussion join the [Google Group](http://groups.google.com/group/jadejs). + +## Test drive + + You can test drive Jade online [here](http://naltatis.github.com/jade-syntax-docs). + +## README Contents + +- [Features](#a1) +- [Implementations](#a2) +- [Installation](#a3) +- [Browser Support](#a4) +- [Public API](#a5) +- [Syntax](#a6) + - [Line Endings](#a6-1) + - [Tags](#a6-2) + - [Tag Text](#a6-3) + - [Comments](#a6-4) + - [Block Comments](#a6-5) + - [Nesting](#a6-6) + - [Block Expansion](#a6-7) + - [Case](#a6-8) + - [Attributes](#a6-9) + - [HTML](#a6-10) + - [Doctypes](#a6-11) +- [Filters](#a7) +- [Code](#a8) +- [Iteration](#a9) +- [Conditionals](#a10) +- [Template inheritance](#a11) +- [Block append / prepend](#a12) +- [Includes](#a13) +- [Mixins](#a14) +- [Generated Output](#a15) +- [Example Makefile](#a16) +- [jade(1)](#a17) +- [Tutorials](#a18) +- [License](#a19) + + +## Features + + - client-side support + - great readability + - flexible indentation + - block-expansion + - mixins + - static includes + - attribute interpolation + - code is escaped by default for security + - contextual error reporting at compile & run time + - executable for compiling jade templates via the command line + - html 5 mode (the default doctype) + - optional memory caching + - combine dynamic and static tag classes + - parse tree manipulation via _filters_ + - template inheritance + - block append / prepend + - supports [Express JS](http://expressjs.com) out of the box + - transparent iteration over objects, arrays, and even non-enumerables via `each` + - block comments + - no tag prefix + - filters + - :stylus must have [stylus](http://github.com/LearnBoost/stylus) installed + - :less must have [less.js](http://github.com/cloudhead/less.js) installed + - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js), [node-discount](http://github.com/visionmedia/node-discount), or [marked](http://github.com/chjj/marked) installed + - :cdata + - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed + - [Emacs Mode](https://github.com/brianc/jade-mode) + - [Vim Syntax](https://github.com/digitaltoad/vim-jade) + - [TextMate Bundle](http://github.com/miksago/jade-tmbundle) + - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode) + - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs) + - [html2jade](https://github.com/donpark/html2jade) converter + + +## Implementations + + - [php](http://github.com/everzet/jade.php) + - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html) + - [ruby](http://github.com/stonean/slim) + - [python](https://github.com/SyrusAkbary/pyjade) + - [java](https://github.com/neuland/jade4j) + + +## Installation + +via npm: + +```bash +$ npm install jade +``` + + +## Browser Support + + To compile jade to a single file compatible for client-side use simply execute: + +```bash +$ make jade.js +``` + + Alternatively, if uglifyjs is installed via npm (`npm install uglify-js`) you may execute the following which will create both files. However each release builds these for you. + +```bash +$ make jade.min.js +``` + + By default Jade instruments templates with line number statements such as `__.lineno = 3` for debugging purposes. When used in a browser it's useful to minimize this boiler plate, you can do so by passing the option `{ compileDebug: false }`. The following template + +```jade +p Hello #{name} +``` + + Can then be as small as the following generated function: + +```js +function anonymous(locals, attrs, escape, rethrow) { + var buf = []; + with (locals || {}) { + var interp; + buf.push('\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\n

    '); + } + return buf.join(""); +} +``` + + Through the use of Jade's `./runtime.js` you may utilize these pre-compiled templates on the client-side _without_ Jade itself, all you need is the associated utility functions (in runtime.js), which are then available as `jade.attrs`, `jade.escape` etc. To enable this you should pass `{ client: true }` to `jade.compile()` to tell Jade to reference the helper functions + via `jade.attrs`, `jade.escape` etc. + +```js +function anonymous(locals, attrs, escape, rethrow) { + var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow; + var buf = []; + with (locals || {}) { + var interp; + buf.push('\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\n

    '); + } + return buf.join(""); +} +``` + +
    +## Public API + +```js +var jade = require('jade'); + +// Compile a function +var fn = jade.compile('string of jade', options); +fn(locals); +``` + +### Options + + - `self` Use a `self` namespace to hold the locals _(false by default)_ + - `locals` Local variable object + - `filename` Used in exceptions, and required when using includes + - `debug` Outputs tokens and function body generated + - `compiler` Compiler to replace jade's default + - `compileDebug` When `false` no debug instrumentation is compiled + - `pretty` Add pretty-indentation whitespace to output _(false by default)_ + + +## Syntax + + +### Line Endings + +**CRLF** and **CR** are converted to **LF** before parsing. + + +### Tags + +A tag is simply a leading word: + +```jade +html +``` + +for example is converted to `` + +tags can also have ids: + +```jade +div#container +``` + +which would render `
    ` + +how about some classes? + +```jade +div.user-details +``` + +renders `
    ` + +multiple classes? _and_ an id? sure: + +```jade +div#foo.bar.baz +``` + +renders `
    ` + +div div div sure is annoying, how about: + +```jade +#foo +.bar +``` + +which is syntactic sugar for what we have already been doing, and outputs: + +```html +
    +``` + +
    +### Tag Text + +Simply place some content after the tag: + +```jade +p wahoo! +``` + +renders `

    wahoo!

    `. + +well cool, but how about large bodies of text: + +```jade +p + | foo bar baz + | rawr rawr + | super cool + | go jade go +``` + +renders `

    foo bar baz rawr.....

    ` + +interpolation? yup! both types of text can utilize interpolation, +if we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following: + +```jade +#user #{name} <#{email}> +``` + +outputs `
    tj <tj@vision-media.ca>
    ` + +Actually want `#{}` for some reason? escape it! + +```jade +p \#{something} +``` + +now we have `

    #{something}

    ` + +We can also utilize the unescaped variant `!{html}`, so the following +will result in a literal script tag: + +```jade +- var html = "" +| !{html} +``` + +Nested tags that also contain text can optionally use a text block: + +```jade +label + | Username: + input(name='user[name]') +``` + +or immediate tag text: + +```jade +label Username: + input(name='user[name]') +``` + +Tags that accept _only_ text such as `script` and `style` do not +need the leading `|` character, for example: + +```jade +html + head + title Example + script + if (foo) { + bar(); + } else { + baz(); + } +``` + +Once again as an alternative, we may use a trailing `.` to indicate a text block, for example: + +```jade +p. + foo asdf + asdf + asdfasdfaf + asdf + asd. +``` + +outputs: + +```html +

    foo asdf +asdf + asdfasdfaf + asdf +asd. +

    +``` + +This however differs from a trailing `.` followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal: + +```jade +p . +``` + +outputs: + +```html +

    .

    +``` + +It should be noted that text blocks should be doubled escaped. For example if you desire the following output. + +```html +

    foo\bar

    +``` + +use: + +```jade +p. + foo\\bar +``` + +
    +### Comments + +Single line comments currently look the same as JavaScript comments, +aka `//` and must be placed on their own line: + +```jade +// just some paragraphs +p foo +p bar +``` + +would output + +```html + +

    foo

    +

    bar

    +``` + +Jade also supports unbuffered comments, by simply adding a hyphen: + +```jade +//- will not output within markup +p foo +p bar +``` + +outputting + +```html +

    foo

    +

    bar

    +``` + +
    +### Block Comments + + A block comment is legal as well: + +```jade +body + // + #content + h1 Example +``` + +outputting + +```html + + + +``` + +Jade supports conditional-comments as well, for example: + +```jade +head + //if lt IE 8 + script(src='/ie-sucks.js') +``` + +outputs: + +```html + + + +``` + + +### Nesting + + Jade supports nesting to define the tags in a natural way: + +```jade +ul + li.first + a(href='#') foo + li + a(href='#') bar + li.last + a(href='#') baz +``` + + +### Block Expansion + + Block expansion allows you to create terse single-line nested tags, + the following example is equivalent to the nesting example above. + +```jade +ul + li.first: a(href='#') foo + li: a(href='#') bar + li.last: a(href='#') baz +``` + + +### Case + + The case statement takes the following form: + +```jade +html + body + friends = 10 + case friends + when 0 + p you have no friends + when 1 + p you have a friend + default + p you have #{friends} friends +``` + + Block expansion may also be used: + +```jade +friends = 5 + +html + body + case friends + when 0: p you have no friends + when 1: p you have a friend + default: p you have #{friends} friends +``` + + +### Attributes + +Jade currently supports `(` and `)` as attribute delimiters. + +```jade +a(href='/login', title='View login page') Login +``` + +When a value is `undefined` or `null` the attribute is _not_ added, +so this is fine, it will not compile `something="null"`. + +```jade +div(something=null) +``` + +Boolean attributes are also supported: + +```jade +input(type="checkbox", checked) +``` + +Boolean attributes with code will only output the attribute when `true`: + +```jade +input(type="checkbox", checked=someValue) +``` + +Multiple lines work too: + +```jade +input(type='checkbox', + name='agreement', + checked) +``` + +Multiple lines without the comma work fine: + +```jade +input(type='checkbox' + name='agreement' + checked) +``` + +Funky whitespace? fine: + +```jade +input( + type='checkbox' + name='agreement' + checked) +``` + +Colons work: + +```jade +rss(xmlns:atom="atom") +``` + +Suppose we have the `user` local `{ id: 12, name: 'tobi' }` +and we wish to create an anchor tag with `href` pointing to "/user/12" +we could use regular javascript concatenation: + +```jade +a(href='/user/' + user.id)= user.name +``` + +or we could use jade's interpolation, which I added because everyone +using Ruby or CoffeeScript seems to think this is legal js..: + +```jade +a(href='/user/#{user.id}')= user.name +``` + +The `class` attribute is special-cased when an array is given, +allowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly: + +```jade +body(class=bodyClasses) +``` + + +### HTML + + Inline html is fine, we can use the pipe syntax to + write arbitrary text, in this case some html: + +```jade +html + body + |

    Title

    + |

    foo bar baz

    +``` + + Or we can use the trailing `.` to indicate to Jade that we + only want text in this block, allowing us to omit the pipes: + +```jade +html + body. +

    Title

    +

    foo bar baz

    +``` + + Both of these examples yield the same result: + +```html +

    Title

    +

    foo bar baz

    + +``` + + The same rule applies for anywhere you can have text + in jade, raw html is fine: + +```jade +html + body + h1 User #{name} +``` + +
    +### Doctypes + +To add a doctype simply use `!!!`, or `doctype` followed by an optional value: + +```jade +!!! +``` + +or + +```jade +doctype +``` + +Will output the _html 5_ doctype, however: + +```jade +!!! transitional +``` + +Will output the _transitional_ doctype. + +Doctypes are case-insensitive, so the following are equivalent: + +```jade +doctype Basic +doctype basic +``` + +it's also possible to simply pass a doctype literal: + +```jade +doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN +``` + +yielding: + +```html + +``` + +Below are the doctypes defined by default, which can easily be extended: + +```js +var doctypes = exports.doctypes = { + '5': '', + 'default': '', + 'xml': '', + 'transitional': '', + 'strict': '', + 'frameset': '', + '1.1': '', + 'basic': '', + 'mobile': '' +}; +``` + +To alter the default simply change: + +```js +jade.doctypes.default = 'whatever you want'; +``` + + +## Filters + +Filters are prefixed with `:`, for example `:markdown` and +pass the following block of text to an arbitrary function for processing. View the _features_ +at the top of this document for available filters. + +```jade +body + :markdown + Woah! jade _and_ markdown, very **cool** + we can even link to [stuff](http://google.com) +``` + +Renders: + +```html +

    Woah! jade and markdown, very cool we can even link to stuff

    +``` + + +## Code + +Jade currently supports three classifications of executable code. The first +is prefixed by `-`, and is not buffered: + +```jade +- var foo = 'bar'; +``` + +This can be used for conditionals, or iteration: + +```jade +- for (var key in obj) + p= obj[key] +``` + +Due to Jade's buffering techniques the following is valid as well: + +```jade +- if (foo) + ul + li yay + li foo + li worked +- else + p oh no! didnt work +``` + +Hell, even verbose iteration: + +```jade +- if (items.length) + ul + - items.forEach(function(item){ + li= item + - }) +``` + +Anything you want! + +Next up we have _escaped_ buffered code, which is used to +buffer a return value, which is prefixed by `=`: + +```jade +- var foo = 'bar' += foo +h1= foo +``` + +Which outputs `bar

    bar

    `. Code buffered by `=` is escaped +by default for security, however to output unescaped return values +you may use `!=`: + +```jade +p!= aVarContainingMoreHTML +``` + + Jade also has designer-friendly variants, making the literal JavaScript + more expressive and declarative. For example the following assignments + are equivalent, and the expression is still regular javascript: + +```jade +- var foo = 'foo ' + 'bar' +foo = 'foo ' + 'bar' +``` + + Likewise Jade has first-class `if`, `else if`, `else`, `until`, `while`, `unless` among others, however you must remember that the expressions are still regular javascript: + +```jade +if foo == 'bar' + ul + li yay + li foo + li worked +else + p oh no! didnt work +``` + +
    +## Iteration + + Along with vanilla JavaScript Jade also supports a subset of + constructs that allow you to create more designer-friendly templates, + one of these constructs is `each`, taking the form: + +```jade +each VAL[, KEY] in OBJ +``` + +An example iterating over an array: + +```jade +- var items = ["one", "two", "three"] +each item in items + li= item +``` + +outputs: + +```html +
  • one
  • +
  • two
  • +
  • three
  • +``` + +iterating an array with index: + +```jade +items = ["one", "two", "three"] +each item, i in items + li #{item}: #{i} +``` + +outputs: + +```html +
  • one: 0
  • +
  • two: 1
  • +
  • three: 2
  • +``` + +iterating an object's keys and values: + +```jade +obj = { foo: 'bar' } +each val, key in obj + li #{key}: #{val} +``` + +would output `
  • foo: bar
  • ` + +Internally Jade converts these statements to regular +JavaScript loops such as `users.forEach(function(user){`, +so lexical scope and nesting applies as it would with regular +JavaScript: + +```jade +each user in users + each role in user.roles + li= role +``` + + You may also use `for` if you prefer: + +```jade +for user in users + for role in user.roles + li= role +``` + +
    +## Conditionals + + Jade conditionals are equivalent to those using the code (`-`) prefix, + however allow you to ditch parenthesis to become more designer friendly, + however keep in mind the expression given is _regular_ JavaScript: + +```jade +for user in users + if user.role == 'admin' + p #{user.name} is an admin + else + p= user.name +``` + + is equivalent to the following using vanilla JavaScript literals: + +```jade +for user in users + - if (user.role == 'admin') + p #{user.name} is an admin + - else + p= user.name +``` + + Jade also provides have `unless` which is equivalent to `if (!(expr))`: + +```jade +for user in users + unless user.isAnonymous + p + | Click to view + a(href='/users/' + user.id)= user.name +``` + + +## Template inheritance + + Jade supports template inheritance via the `block` and `extends` keywords. A block is simply a "block" of Jade that may be replaced within a child template, this process is recursive. To activate template inheritance in Express 2.x you must add: `app.set('view options', { layout: false });`. + + Jade blocks can provide default content if desired, however optional as shown below by `block scripts`, `block content`, and `block foot`. + +```jade +html + head + h1 My Site - #{title} + block scripts + script(src='/jquery.js') + body + block content + block foot + #footer + p some footer content +``` + + Now to extend the layout, simply create a new file and use the `extends` directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the `foot` block is _not_ redefined and will output "some footer content". + +```jade +extends layout + +block scripts + script(src='/jquery.js') + script(src='/pets.js') + +block content + h1= title + each pet in pets + include pet +``` + + It's also possible to override a block to provide additional blocks, as shown in the following example where `content` now exposes a `sidebar` and `primary` block for overriding, or the child template could override `content` all together. + +```jade +extends regular-layout + +block content + .sidebar + block sidebar + p nothing + .primary + block primary + p nothing +``` + + +## Block append / prepend + + Jade allows you to _replace_ (default), _prepend_, or _append_ blocks. Suppose for example you have default scripts in a "head" block that you wish to utilize on _every_ page, you might do this: + +```jade +html + head + block head + script(src='/vendor/jquery.js') + script(src='/vendor/caustic.js') + body + block content +``` + + Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply `append` the block: + +```jade +extends layout + +block append head + script(src='/vendor/three.js') + script(src='/game.js') +``` + + When using `block append` or `block prepend` the `block` is optional: + +```jade +extends layout + +append head + script(src='/vendor/three.js') + script(src='/game.js') +``` + + +## Includes + + Includes allow you to statically include chunks of Jade, + or other content like css, or html which lives in separate files. The classical example is including a header and footer. Suppose we have the following directory structure: + + ./layout.jade + ./includes/ + ./head.jade + ./foot.jade + +and the following _layout.jade_: + +```jade +html + include includes/head + body + h1 My Site + p Welcome to my super amazing site. + include includes/foot +``` + +both includes _includes/head_ and _includes/foot_ are +read relative to the `filename` option given to _layout.jade_, +which should be an absolute path to this file, however Express does this for you. Include then parses these files, and injects the AST produced to render what you would expect: + +```html + + + My Site + + + +

    My Site

    +

    Welcome to my super lame site.

    + + + +``` + + As mentioned `include` can be used to include other content + such as html or css. By providing an extension Jade will not + assume that the file is Jade source and will include it as + a literal: + +```jade +html + body + include content.html +``` + + Include directives may also accept a block, in which case the + the given block will be appended to the _last_ block defined + in the file. For example if `head.jade` contains: + +```jade +head + script(src='/jquery.js') +``` + + We may append values by providing a block to `include head` + as shown below, adding the two scripts. + +```jade +html + include head + script(src='/foo.js') + script(src='/bar.js') + body + h1 test +``` + + You may also `yield` within an included template, allowing you to explicitly mark where the block given to `include` will be placed. Suppose for example you wish to prepend scripts rather than append, you might do the following: + +```jade +head + yield + script(src='/jquery.js') + script(src='/jquery.ui.js') +``` + + Since included Jade is parsed and literally merges the AST, lexically scoped variables function as if the included Jade was written right in the same file. This means `include` may be used as sort of partial, for example suppose we have `user.jade` which utilizes a `user` variable. + +```jade +h1= user.name +p= user.occupation +``` + +We could then simply `include user` while iterating users, and since the `user` variable is already defined within the loop the included template will have access to it. + +```jade +users = [{ name: 'Tobi', occupation: 'Ferret' }] + +each user in users + .user + include user +``` + +yielding: + +```html +
    +

    Tobi

    +

    Ferret

    +
    +``` + +If we wanted to expose a different variable name as `user` since `user.jade` references that name, we could simply define a new variable as shown here with `user = person`: + +```jade +each person in users + .user + user = person + include user +``` + +
    +## Mixins + + Mixins are converted to regular JavaScript functions in + the compiled template that Jade constructs. Mixins may + take arguments, though not required: + +```jade +mixin list + ul + li foo + li bar + li baz +``` + + Utilizing a mixin without args looks similar, just without a block: + +```jade +h2 Groceries +mixin list +``` + + Mixins may take one or more arguments as well, the arguments + are regular javascripts expressions, so for example the following: + +```jade +mixin pets(pets) + ul.pets + - each pet in pets + li= pet + +mixin profile(user) + .user + h2= user.name + mixin pets(user.pets) +``` + + Would yield something similar to the following html: + +```html +
    +

    tj

    +
      +
    • tobi
    • +
    • loki
    • +
    • jane
    • +
    • manny
    • +
    +
    +``` + +
    +## Generated Output + + Suppose we have the following Jade: + +```jade +- var title = 'yay' +h1.title #{title} +p Just an example +``` + + When the `compileDebug` option is not explicitly `false`, Jade + will compile the function instrumented with `__.lineno = n;`, which + in the event of an exception is passed to `rethrow()` which constructs + a useful message relative to the initial Jade input. + +```js +function anonymous(locals) { + var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" }; + var rethrow = jade.rethrow; + try { + var attrs = jade.attrs, escape = jade.escape; + var buf = []; + with (locals || {}) { + var interp; + __.lineno = 1; + var title = 'yay' + __.lineno = 2; + buf.push(''); + buf.push('' + escape((interp = title) == null ? '' : interp) + ''); + buf.push(''); + __.lineno = 3; + buf.push('

    '); + buf.push('Just an example'); + buf.push('

    '); + } + return buf.join(""); + } catch (err) { + rethrow(err, __.input, __.filename, __.lineno); + } +} +``` + +When the `compileDebug` option _is_ explicitly `false`, this instrumentation +is stripped, which is very helpful for light-weight client-side templates. Combining Jade's options with the `./runtime.js` file in this repo allows you +to toString() compiled templates and avoid running the entire Jade library on +the client, increasing performance, and decreasing the amount of JavaScript +required. + +```js +function anonymous(locals) { + var attrs = jade.attrs, escape = jade.escape; + var buf = []; + with (locals || {}) { + var interp; + var title = 'yay' + buf.push(''); + buf.push('' + escape((interp = title) == null ? '' : interp) + ''); + buf.push(''); + buf.push('

    '); + buf.push('Just an example'); + buf.push('

    '); + } + return buf.join(""); +} +``` + +
    +## Example Makefile + + Below is an example Makefile used to compile _pages/*.jade_ + into _pages/*.html_ files by simply executing `make`. + +```make +JADE = $(shell find pages/*.jade) +HTML = $(JADE:.jade=.html) + +all: $(HTML) + +%.html: %.jade + jade < $< --path $< > $@ + +clean: + rm -f $(HTML) + +.PHONY: clean +``` + +this can be combined with the `watch(1)` command to produce +a watcher-like behaviour: + +```bash +$ watch make +``` + + +## jade(1) + +``` + +Usage: jade [options] [dir|file ...] + +Options: + + -h, --help output usage information + -V, --version output the version number + -o, --obj javascript options object + -O, --out output the compiled html to + -p, --path filename used to resolve includes + -P, --pretty compile pretty html output + -c, --client compile for client-side runtime.js + -D, --no-debug compile without debugging (smaller functions) + +Examples: + + # translate jade the templates dir + $ jade templates + + # create {foo,bar}.html + $ jade {foo,bar}.jade + + # jade over stdio + $ jade < my.jade > my.html + + # jade over stdio + $ echo "h1 Jade!" | jade + + # foo, bar dirs rendering to /tmp + $ jade foo bar --out /tmp + +``` + + +## Tutorials + + - cssdeck interactive [Jade syntax tutorial](http://cssdeck.com/labs/learning-the-jade-templating-engine-syntax) + - cssdeck interactive [Jade logic tutorial](http://cssdeck.com/labs/jade-templating-tutorial-codecast-part-2) + - in [Japanese](http://blog.craftgear.net/4f501e97c1347ec934000001/title/10%E5%88%86%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8Bjade%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3) + + +## License + +(The MIT License) + +Copyright (c) 2009-2010 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. diff --git a/node_modules/jade/Readme_zh-cn.md b/node_modules/jade/Readme_zh-cn.md new file mode 100644 index 0000000..cb90608 --- /dev/null +++ b/node_modules/jade/Readme_zh-cn.md @@ -0,0 +1,921 @@ +# Jade - 模板引擎 + + Jade 是一个高性能的模板引擎,它深受[Haml](http://haml-lang.com)影响,它是用javascript实现的,并且可以供[node](http://nodejs.org)使用. + + 翻译:[草依山](http://jser.me)   [翻译反馈](http://weibo.com/1826461472/z9jriDdmB#pl_profile_nav)  [Fork me](https://github.com/jserme/jade/) + +## 特性 + + - 客户端支持 + - 代码高可读 + - 灵活的缩进 + - 块展开 + - 混合 + - 静态包含 + - 属性改写 + - 安全,默认代码是转义的 + - 运行时和编译时上下文错误报告 + - 命令行下编译jade模板 + - html 5 模式 (使用 _!!! 5_ 文档类型) + - 在内存中缓存(可选) + - 合并动态和静态标签类 + - 可以通过 _filters_ 修改树 + - 模板继承 + - 原生支持 [Express JS](http://expressjs.com) + - 通过 `each` 枚举对象、数组甚至是不能枚举的对象 + - 块注释 + - 没有前缀的标签 + - AST filters + - 过滤器 + - :sass 必须已经安装[sass.js](http://github.com/visionmedia/sass.js) + - :less 必须已经安装[less.js](http://github.com/cloudhead/less.js) + - :markdown 必须已经安装[markdown-js](http://github.com/evilstreak/markdown-js) 或者[node-discount](http://github.com/visionmedia/node-discount) + - :cdata + - :coffeescript 必须已经安装[coffee-script](http://jashkenas.github.com/coffee-script/) + - [Vim Syntax](https://github.com/digitaltoad/vim-jade) + - [TextMate Bundle](http://github.com/miksago/jade-tmbundle) + - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs) + - [html2jade](https://github.com/donpark/html2jade) 转换器 + +## 其它实现 + + - [php](http://github.com/everzet/jade.php) + - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html) + - [ruby](http://github.com/stonean/slim) + +## 安装 + +通过 npm: + + npm install jade + +## 浏览器支持 + + 把jade编译为一个可供浏览器使用的单文件,只需要简单的执行: + + $ make jade.js + + 如果你已经安装了uglifyjs (`npm install uglify-js`),你可以执行下面的命令它会生成所有的文件。其实每一个正式版本里都帮你做了这事。 + + $ make jade.min.js + + 默认情况下,为了方便调试Jade会把模板组织成带有形如 `__.lineno = 3` 的行号的形式。 + 在浏览器里使用的时候,你可以通过传递一个选项`{ compileDebug: false }`来去掉这个。 + 下面的模板 + + p Hello #{name} + + 会被翻译成下面的函数: + +```js +function anonymous(locals, attrs, escape, rethrow) { + var buf = []; + with (locals || {}) { + var interp; + buf.push('\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\n

    '); + } + return buf.join(""); +} +``` + + 通过使用Jade的 `./runtime.js`你可以在浏览器使用这些预编译的模板而不需要使用Jade, 你只需要使用runtime.js里的工具函数, 它们会放在`jade.attrs`, `jade.escape` 这些里。 把选项 `{ client: true }` 传递给 `jade.compile()`, Jade 会把这些帮助函数的引用放在`jade.attrs`, `jade.escape`. + +```js +function anonymous(locals, attrs, escape, rethrow) { + var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow; + var buf = []; + with (locals || {}) { + var interp; + buf.push('\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\n

    '); + } + return buf.join(""); +} +``` + +## 公开API + +```javascript + var jade = require('jade'); + + // Compile a function + var fn = jade.compile('string of jade', options); + fn(locals); +``` + +### 选项 + + - `self` 使用`self` 命名空间来持有本地变量. _默认为false_ + - `locals` 本地变量对象 + - `filename` 异常发生时使用,includes时必需 + - `debug` 输出token和翻译后的函数体 + - `compiler` 替换掉jade默认的编译器 + - `compileDebug` `false`的时候调试的结构不会被输出 + +## 语法 + +### 行结束标志 + +**CRLF** 和 **CR** 会在编译之前被转换为 **LF** + +### 标签 + +标签就是一个简单的单词: + + html + +它会被转换为 `` + +标签也是可以有id的: + + div#container + +它会被转换为 `
    ` + +怎么加类呢? + + div.user-details + +转换为 `
    ` + +多个类? 和id? 也是可以搞定的: + + div#foo.bar.baz + +转换为 `
    ` + +不停的div div div 很讨厌啊 , 可以这样: + + #foo + .bar + +这个算是我们的语法糖,它已经被很好的支持了,上面的会输出: + + `
    ` + +### 标签文本 + +只需要简单的把内容放在标签之后: + + p wahoo! + +它会被渲染为 `

    wahoo!

    `. + +很帅吧,但是大段的文本怎么办呢: + + p + | foo bar baz + | rawr rawr + | super cool + | go jade go + +渲染为 `

    foo bar baz rawr.....

    ` + +怎么和数据结合起来? 所有类型的文本展示都可以和数据结合起来,如果我们把`{ name: 'tj', email: 'tj@vision-media.ca' }` 传给编译函数,下面是模板上的写法: + + #user #{name} <#{email}> + +它会被渲染为 `
    tj <tj@vision-media.ca>
    ` + +当就是要输出`#{}` 的时候怎么办? 转义一下! + + p \#{something} + +它会输出`

    #{something}

    ` + +同样可以使用非转义的变量`!{html}`, 下面的模板将直接输出一个script标签 + + - var html = "" + | !{html} + +内联标签同样可以使用文本块来包含文本: + + label + | Username: + input(name='user[name]') + +或者直接使用标签文本: + + label Username: + input(name='user[name]') + +_只_包含文本的标签,比如`script`, `style`, 和 `textarea` 不需要前缀`|` 字符, 比如: + + html + head + title Example + script + if (foo) { + bar(); + } else { + baz(); + } + +这里还有一种选择,可以使用'.' 来开始一段文本块,比如: + + p. + foo asdf + asdf + asdfasdfaf + asdf + asd. + +会被渲染为: + +

    foo asdf + asdf + asdfasdfaf + asdf + asd + . +

    + +这和带一个空格的 '.' 是不一样的, 带空格的会被Jade的解析器忽略,当作一个普通的文字: + + p . + +渲染为: + +

    .

    + + +需要注意的是广西块需要两次转义。比如想要输出下面的文本: + +

    foo\bar

    + +使用: + + p. + foo\\bar + +### 注释 + +单行注释和JavaScript里是一样的,通过"//"来开始,并且必须单独一行: + + // just some paragraphs + p foo + p bar + +渲染为: + + +

    foo

    +

    bar

    + +Jade 同样支持不输出的注释,加一个短横线就行了: + + //- will not output within markup + p foo + p bar + +渲染为: + +

    foo

    +

    bar

    + +### 块注释 + + 块注释也是支持的: + + body + // + #content + h1 Example + +渲染为: + + + + + +Jade 同样很好的支持了条件注释: + + body + //if IE + a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox + + +渲染为: + + + + + +### 内联 + + Jade 支持以自然的方式定义标签嵌套: + + ul + li.first + a(href='#') foo + li + a(href='#') bar + li.last + a(href='#') baz + +### 块展开 + + 块展开可以帮助你在一行内创建嵌套的标签,下面的例子和上面的是一样的: + + ul + li.first: a(href='#') foo + li: a(href='#') bar + li.last: a(href='#') baz + + +### 属性 + +Jade 现在支持使用'(' 和 ')' 作为属性分隔符 + + a(href='/login', title='View login page') Login + +当一个值是 `undefined` 或者 `null` 属性_不_会被加上, +所以呢,它不会编译出 'something="null"'. + + div(something=null) + +Boolean 属性也是支持的: + + input(type="checkbox", checked) + +使用代码的Boolean 属性只有当属性为`true`时才会输出: + + input(type="checkbox", checked=someValue) + +多行同样也是可用的: + + input(type='checkbox', + name='agreement', + checked) + +多行的时候可以不加逗号: + + input(type='checkbox' + name='agreement' + checked) + +加点空格,格式好看一点?同样支持 + + input( + type='checkbox' + name='agreement' + checked) + +冒号也是支持的: + + rss(xmlns:atom="atom") + +假如我有一个`user` 对象 `{ id: 12, name: 'tobi' }` +我们希望创建一个指向"/user/12"的链接 `href`, 我们可以使用普通的javascript字符串连接,如下: + + a(href='/user/' + user.id)= user.name + +或者我们使用jade的修改方式,这个我想很多使用Ruby或者 CoffeeScript的人会看起来像普通的js..: + + a(href='/user/#{user.id}')= user.name + +`class`属性是一个特殊的属性,你可以直接传递一个数组,比如`bodyClasses = ['user', 'authenticated']` : + + body(class=bodyClasses) + +### HTML + + 内联的html是可以的,我们可以使用管道定义一段文本 : + +``` +html + body + |

    Title

    + |

    foo bar baz

    +``` + + 或者我们可以使用`.` 来告诉Jade我们需要一段文本: + +``` +html + body. +

    Title

    +

    foo bar baz

    +``` + + 上面的两个例子都会渲染成相同的结果: + +``` +

    Title

    +

    foo bar baz

    + +``` + + 这条规则适应于在jade里的任何文本: + +``` +html + body + h1 User #{name} +``` + +### Doctypes + +添加文档类型只需要简单的使用 `!!!`, 或者 `doctype` 跟上下面的可选项: + + !!! + +会渲染出 _transitional_ 文档类型, 或者: + + !!! 5 + +or + + !!! html + +or + + doctype html + +doctypes 是大小写不敏感的, 所以下面两个是一样的: + + doctype Basic + doctype basic + +当然也是可以直接传递一段文档类型的文本: + + doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN + +渲染后: + + + +会输出 _html 5_ 文档类型. 下面的默认的文档类型,可以很简单的扩展: + +```javascript + var doctypes = exports.doctypes = { + '5': '', + 'xml': '', + 'default': '', + 'transitional': '', + 'strict': '', + 'frameset': '', + '1.1': '', + 'basic': '', + 'mobile': '' + }; +``` + +通过下面的代码可以很简单的改变默认的文档类型: + +```javascript + jade.doctypes.default = 'whatever you want'; +``` + +## 过滤器 + +过滤器前缀 `:`, 比如 `:markdown` 会把下面块里的文本交给专门的函数进行处理。查看顶部 _特性_ 里有哪些可用的过滤器。 + + body + :markdown + Woah! jade _and_ markdown, very **cool** + we can even link to [stuff](http://google.com) + +渲染为: + +

    Woah! jade and markdown, very cool we can even link to stuff

    + +## 代码 + +Jade目前支持三种类型的可执行代码。第一种是前缀`-`, 这是不会被输出的: + + - var foo = 'bar'; + +这可以用在条件语句或者循环中: + + - for (var key in obj) + p= obj[key] + +由于Jade的缓存技术,下面的代码也是可以的: + + - if (foo) + ul + li yay + li foo + li worked + - else + p oh no! didnt work + +哈哈,甚至是很长的循环也是可以的: + + - if (items.length) + ul + - items.forEach(function(item){ + li= item + - }) + +所以你想要的! + +下一步我们要_转义_输出的代码,比如我们返回一个值,只要前缀一个`=`: + + - var foo = 'bar' + = foo + h1= foo + +它会渲染为`bar

    bar

    `. 为了安全起见,使用`=`输出的代码默认是转义的,如果想直接输出不转义的值可以使用`!=`: + + p!= aVarContainingMoreHTML + +Jade 同样是设计师友好的,它可以使javascript更直接更富表现力。比如下面的赋值语句是相等的,同时表达式还是通常的javascript: + + - var foo = 'foo ' + 'bar' + foo = 'foo ' + 'bar' + +Jade会把 `if`, `else if`, `else`, `until`, `while`, `unless`同别的优先对待, 但是你得记住它们还是普通的javascript: + + if foo == 'bar' + ul + li yay + li foo + li worked + else + p oh no! didnt work + +## 循环 + +尽管已经支持JavaScript原生代码,Jade还是支持了一些特殊的标签,它们可以让模板更加易于理解,其中之一就是`each`, 这种形式: + + each VAL[, KEY] in OBJ + +一个遍历数组的例子 : + + - var items = ["one", "two", "three"] + each item in items + li= item + +渲染为: + +
  • one
  • +
  • two
  • +
  • three
  • + +遍历一个数组同时带上索引: + + items = ["one", "two", "three"] + each item, i in items + li #{item}: #{i} + +渲染为: + +
  • one: 0
  • +
  • two: 1
  • +
  • three: 2
  • + +遍历一个数组的键值: + + obj = { foo: 'bar' } + each val, key in obj + li #{key}: #{val} + +将会渲染为:`
  • foo: bar
  • ` + +Jade在内部会把这些语句转换成原生的JavaScript语句,就像使用 `users.forEach(function(user){`, +词法作用域和嵌套会像在普通的JavaScript中一样: + + each user in users + each role in user.roles + li= role + +如果你喜欢,也可以使用`for` : + + for user in users + for role in user.roles + li= role + +## 条件语句 + +Jade 条件语句和使用了(`-`) 前缀的JavaScript语句是一致的,然后它允许你不使用圆括号,这样会看上去对设计师更友好一点, +同时要在心里记住这个表达式渲染出的是_常规_Javascript: + + for user in users + if user.role == 'admin' + p #{user.name} is an admin + else + p= user.name + +和下面的使用了常规JavaScript的代码是相等的: + + for user in users + - if (user.role == 'admin') + p #{user.name} is an admin + - else + p= user.name + +Jade 同时支持`unless`, 这和`if (!(expr))`是等价的: + + for user in users + unless user.isAnonymous + p + | Click to view + a(href='/users/' + user.id)= user.name + +## 模板继承 + + Jade 支持通过 `block` 和 `extends` 关键字来实现模板继承。 一个块就是一个Jade的"block" ,它将在子模板中实现,同时是支持递归的。 + + Jade 块如果没有内容,Jade会添加默认内容,下面的代码默认会输出`block scripts`, `block content`, 和 `block foot`. + +``` +html + head + h1 My Site - #{title} + block scripts + script(src='/jquery.js') + body + block content + block foot + #footer + p some footer content +``` + + 现在我们来继承这个布局,简单创建一个新文件,像下面那样直接使用`extends`,给定路径(可以选择带.jade扩展名或者不带). 你可以定义一个或者更多的块来覆盖父级块内容, 注意到这里的`foot`块_没有_定义,所以它还会输出父级的"some footer content"。 + +``` +extends extend-layout + +block scripts + script(src='/jquery.js') + script(src='/pets.js') + +block content + h1= title + each pet in pets + include pet +``` + + 同样可以在一个子块里添加块,就像下面实现的块`content`里又定义了两个可以被实现的块`sidebar`和`primary`,或者子模板直接实现`content`。 + +``` +extends regular-layout + +block content + .sidebar + block sidebar + p nothing + .primary + block primary + p nothing +``` + +## 包含 + + Includes 允许你静态包含一段Jade, 或者别的存放在单个文件中的东西比如css, html。 非常常见的例子是包含头部和页脚。 假设我们有一个下面目录结构的文件夹: + + ./layout.jade + ./includes/ + ./head.jade + ./tail.jade + +下面是 _layout.jade_ 的内容: + + html + include includes/head + body + h1 My Site + p Welcome to my super amazing site. + include includes/foot + +这两个包含 _includes/head_ 和 _includes/foot_ 都会读取相对于给 _layout.jade_ 参数`filename` 的路径的文件, 这是一个绝对路径,不用担心Express帮你搞定这些了。Include 会解析这些文件,并且插入到已经生成的语法树中,然后渲染为你期待的内容: + +```html + + + My Site + + + +

    My Site

    +

    Welcome to my super lame site.

    + + + +``` + + 前面已经提到,`include` 可以包含比如html或者css这样的内容。给定一个扩展名后,Jade不会把这个文件当作一个Jade源代码,并且会把它当作一个普通文本包含进来: + +``` +html + body + include content.html +``` + + Include 也可以接受块内容,给定的块将会附加到包含文件 _最后_ 的块里。 举个例子,`head.jade` 包含下面的内容: + + + ``` +head + script(src='/jquery.js') +``` + + 我们可以像下面给`include head`添加内容, 这里是添加两个脚本. + +``` +html + include head + script(src='/foo.js') + script(src='/bar.js') + body + h1 test +``` + + +## Mixins + + Mixins在编译的模板里会被Jade转换为普通的JavaScript函数。 Mixins 可以还参数,但不是必需的: + + mixin list + ul + li foo + li bar + li baz + + 使用不带参数的mixin看上去非常简单,在一个块外: + + h2 Groceries + mixin list + + Mixins 也可以带一个或者多个参数,参数就是普通的javascripts表达式,比如下面的例子: + + mixin pets(pets) + ul.pets + - each pet in pets + li= pet + + mixin profile(user) + .user + h2= user.name + mixin pets(user.pets) + + 会输出像下面的html: + +```html +
    +

    tj

    +
      +
    • tobi
    • +
    • loki
    • +
    • jane
    • +
    • manny
    • +
    +
    +``` + +## 产生输出 + + 假设我们有下面的Jade源码: + +``` +- var title = 'yay' +h1.title #{title} +p Just an example +``` + + 当 `compileDebug` 选项不是`false`, Jade 会编译时会把函数里加上 `__.lineno = n;`, 这个参数会在编译出错时传递给`rethrow()`, 而这个函数会在Jade初始输出时给出一个有用的错误信息。 + +```js +function anonymous(locals) { + var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" }; + var rethrow = jade.rethrow; + try { + var attrs = jade.attrs, escape = jade.escape; + var buf = []; + with (locals || {}) { + var interp; + __.lineno = 1; + var title = 'yay' + __.lineno = 2; + buf.push(''); + buf.push('' + escape((interp = title) == null ? '' : interp) + ''); + buf.push(''); + __.lineno = 3; + buf.push('

    '); + buf.push('Just an example'); + buf.push('

    '); + } + return buf.join(""); + } catch (err) { + rethrow(err, __.input, __.filename, __.lineno); + } +} +``` + +当`compileDebug` 参数是`false`, 这个参数会被去掉,这样对于轻量级的浏览器端模板是非常有用的。结合Jade的参数和当前源码库里的 `./runtime.js` 文件,你可以通过toString()来编译模板而不需要在浏览器端运行整个Jade库,这样可以提高性能,也可以减少载入的JavaScript数量。 + +```js +function anonymous(locals) { + var attrs = jade.attrs, escape = jade.escape; + var buf = []; + with (locals || {}) { + var interp; + var title = 'yay' + buf.push(''); + buf.push('' + escape((interp = title) == null ? '' : interp) + ''); + buf.push(''); + buf.push('

    '); + buf.push('Just an example'); + buf.push('

    '); + } + return buf.join(""); +} +``` + +## Makefile的一个例子 + + 通过执行`make`, 下面的Makefile例子可以把 _pages/*.jade_ 编译为 _pages/*.html_ 。 + +```make +JADE = $(shell find pages/*.jade) +HTML = $(JADE:.jade=.html) + +all: $(HTML) + +%.html: %.jade + jade < $< --path $< > $@ + +clean: + rm -f $(HTML) + +.PHONY: clean +``` + +这个可以和`watch(1)` 命令起来产生像下面的行为: + + $ watch make + +## 命令行的jade(1) + +``` + +使用: jade [options] [dir|file ...] + +选项: + + -h, --help 输出帮助信息 + -v, --version 输出版本号 + -o, --obj javascript选项 + -O, --out 输出编译后的html到 + -p, --path 在处理stdio时,查找包含文件时的查找路径 + +Examples: + + # 编译整个目录 + $ jade templates + + # 生成 {foo,bar}.html + $ jade {foo,bar}.jade + + # 在标准IO下使用jade + $ jade < my.jade > my.html + + # 在标准IO下使用jade, 同时指定用于查找包含的文件 + $ jade < my.jade -p my.jade > my.html + + # 在标准IO下使用jade + $ echo "h1 Jade!" | jade + + # foo, bar 目录渲染到 /tmp + $ jade foo bar --out /tmp + +``` + +## License + +(The MIT License) + +Copyright (c) 2009-2010 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. diff --git a/node_modules/jade/bin/jade b/node_modules/jade/bin/jade new file mode 100755 index 0000000..8f1c816 --- /dev/null +++ b/node_modules/jade/bin/jade @@ -0,0 +1,168 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var fs = require('fs') + , program = require('commander') + , path = require('path') + , basename = path.basename + , dirname = path.dirname + , resolve = path.resolve + , exists = fs.existsSync || path.existsSync + , join = path.join + , mkdirp = require('mkdirp') + , jade = require('../'); + +// jade options + +var options = {}; + +// options + +program + .version(jade.version) + .usage('[options] [dir|file ...]') + .option('-o, --obj ', 'javascript options object') + .option('-O, --out ', 'output the compiled html to ') + .option('-p, --path ', 'filename used to resolve includes') + .option('-P, --pretty', 'compile pretty html output') + .option('-c, --client', 'compile function for client-side runtime.js') + .option('-D, --no-debug', 'compile without debugging (smaller functions)') + .option('-w, --watch', 'watch files for changes and automatically re-render') + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' # translate jade the templates dir'); + console.log(' $ jade templates'); + console.log(''); + console.log(' # create {foo,bar}.html'); + console.log(' $ jade {foo,bar}.jade'); + console.log(''); + console.log(' # jade over stdio'); + console.log(' $ jade < my.jade > my.html'); + console.log(''); + console.log(' # jade over stdio'); + console.log(' $ echo "h1 Jade!" | jade'); + console.log(''); + console.log(' # foo, bar dirs rendering to /tmp'); + console.log(' $ jade foo bar --out /tmp '); + console.log(''); +}); + +program.parse(process.argv); + +// options given, parse them + +if (program.obj) { + if (exists(program.obj)) { + options = JSON.parse(fs.readFileSync(program.obj)); + } else { + options = eval('(' + program.obj + ')'); + } +} + +// --filename + +if (program.path) options.filename = program.path; + +// --no-debug + +options.compileDebug = program.debug; + +// --client + +options.client = program.client; + +// --pretty + +options.pretty = program.pretty; + +// --watch + +options.watch = program.watch; + +// left-over args are file paths + +var files = program.args; + +// compile files + +if (files.length) { + console.log(); + files.forEach(renderFile); + if (options.watch) { + files.forEach(function (file) { + fs.watchFile(file, {interval: 100}, function (curr, prev) { + if (curr.mtime > prev.mtime) renderFile(file); + }); + }); + } + process.on('exit', function () { + console.log(); + }); +// stdio +} else { + stdin(); +} + +/** + * Compile from stdin. + */ + +function stdin() { + var buf = ''; + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(chunk){ buf += chunk; }); + process.stdin.on('end', function(){ + var fn = jade.compile(buf, options); + var output = options.client + ? fn.toString() + : fn(options); + process.stdout.write(output); + }).resume(); +} + +/** + * Process the given path, compiling the jade files found. + * Always walk the subdirectories. + */ + +function renderFile(path) { + var re = /\.jade$/; + fs.lstat(path, function(err, stat) { + if (err) throw err; + // Found jade file + if (stat.isFile() && re.test(path)) { + fs.readFile(path, 'utf8', function(err, str){ + if (err) throw err; + options.filename = path; + var fn = jade.compile(str, options); + var extname = options.client ? '.js' : '.html'; + path = path.replace(re, extname); + if (program.out) path = join(program.out, basename(path)); + var dir = resolve(dirname(path)); + mkdirp(dir, 0755, function(err){ + if (err) throw err; + var output = options.client + ? fn.toString() + : fn(options); + fs.writeFile(path, output, function(err){ + if (err) throw err; + console.log(' \033[90mrendered \033[36m%s\033[0m', path); + }); + }); + }); + // Found directory + } else if (stat.isDirectory()) { + fs.readdir(path, function(err, files) { + if (err) throw err; + files.map(function(filename) { + return path + '/' + filename; + }).forEach(renderFile); + }); + } + }); +} diff --git a/node_modules/jade/index.js b/node_modules/jade/index.js new file mode 100644 index 0000000..8ad059f --- /dev/null +++ b/node_modules/jade/index.js @@ -0,0 +1,4 @@ + +module.exports = process.env.JADE_COV + ? require('./lib-cov/jade') + : require('./lib/jade'); \ No newline at end of file diff --git a/node_modules/jade/jade.js b/node_modules/jade/jade.js new file mode 100644 index 0000000..ad22ec3 --- /dev/null +++ b/node_modules/jade/jade.js @@ -0,0 +1,3654 @@ +(function() { + +// CommonJS require() + +function require(p){ + var path = require.resolve(p) + , mod = require.modules[path]; + if (!mod) throw new Error('failed to require "' + p + '"'); + if (!mod.exports) { + mod.exports = {}; + mod.call(mod.exports, mod, mod.exports, require.relative(path)); + } + return mod.exports; + } + +require.modules = {}; + +require.resolve = function (path){ + var orig = path + , reg = path + '.js' + , index = path + '/index.js'; + return require.modules[reg] && reg + || require.modules[index] && index + || orig; + }; + +require.register = function (path, fn){ + require.modules[path] = fn; + }; + +require.relative = function (parent) { + return function(p){ + if ('.' != p.charAt(0)) return require(p); + + var path = parent.split('/') + , segs = p.split('/'); + path.pop(); + + for (var i = 0; i < segs.length; i++) { + var seg = segs[i]; + if ('..' == seg) path.pop(); + else if ('.' != seg) path.push(seg); + } + + return require(path.join('/')); + }; + }; + + +require.register("compiler.js", function(module, exports, require){ + +/*! + * Jade - Compiler + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var nodes = require('./nodes') + , filters = require('./filters') + , doctypes = require('./doctypes') + , selfClosing = require('./self-closing') + , runtime = require('./runtime') + , utils = require('./utils'); + + + if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } + } + + if (!String.prototype.trimLeft) { + String.prototype.trimLeft = function(){ + return this.replace(/^\s+/, ''); + } + } + + + +/** + * Initialize `Compiler` with the given `node`. + * + * @param {Node} node + * @param {Object} options + * @api public + */ + +var Compiler = module.exports = function Compiler(node, options) { + this.options = options = options || {}; + this.node = node; + this.hasCompiledDoctype = false; + this.hasCompiledTag = false; + this.pp = options.pretty || false; + this.debug = false !== options.compileDebug; + this.indents = 0; + this.parentIndents = 0; + if (options.doctype) this.setDoctype(options.doctype); +}; + +/** + * Compiler prototype. + */ + +Compiler.prototype = { + + /** + * Compile parse tree to JavaScript. + * + * @api public + */ + + compile: function(){ + this.buf = ['var interp;']; + if (this.pp) this.buf.push("var __indent = [];"); + this.lastBufferedIdx = -1; + this.visit(this.node); + return this.buf.join('\n'); + }, + + /** + * Sets the default doctype `name`. Sets terse mode to `true` when + * html 5 is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {string} name + * @api public + */ + + setDoctype: function(name){ + name = (name && name.toLowerCase()) || 'default'; + this.doctype = doctypes[name] || ''; + this.terse = this.doctype.toLowerCase() == ''; + this.xml = 0 == this.doctype.indexOf(' 1 && !escape && block.nodes[0].isText && block.nodes[1].isText) + this.prettyIndent(1, true); + + for (var i = 0; i < len; ++i) { + // Pretty print text + if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText) + this.prettyIndent(1, false); + + this.visit(block.nodes[i]); + // Multiple text nodes are separated by newlines + if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText) + this.buffer('\\n'); + } + }, + + /** + * Visit `doctype`. Sets terse mode to `true` when html 5 + * is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {Doctype} doctype + * @api public + */ + + visitDoctype: function(doctype){ + if (doctype && (doctype.val || !this.doctype)) { + this.setDoctype(doctype.val || 'default'); + } + + if (this.doctype) this.buffer(this.doctype); + this.hasCompiledDoctype = true; + }, + + /** + * Visit `mixin`, generating a function that + * may be called within the template. + * + * @param {Mixin} mixin + * @api public + */ + + visitMixin: function(mixin){ + var name = mixin.name.replace(/-/g, '_') + '_mixin' + , args = mixin.args || '' + , block = mixin.block + , attrs = mixin.attrs + , pp = this.pp; + + if (mixin.call) { + if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');") + if (block || attrs.length) { + + this.buf.push(name + '.call({'); + + if (block) { + this.buf.push('block: function(){'); + + // Render block with no indents, dynamically added when rendered + this.parentIndents++; + var _indents = this.indents; + this.indents = 0; + this.visit(mixin.block); + this.indents = _indents; + this.parentIndents--; + + if (attrs.length) { + this.buf.push('},'); + } else { + this.buf.push('}'); + } + } + + if (attrs.length) { + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push('attributes: merge({' + val.buf + + '}, attributes), escaped: merge(' + val.escaped + ', escaped, true)'); + } else { + this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped); + } + } + + if (args) { + this.buf.push('}, ' + args + ');'); + } else { + this.buf.push('});'); + } + + } else { + this.buf.push(name + '(' + args + ');'); + } + if (pp) this.buf.push("__indent.pop();") + } else { + this.buf.push('var ' + name + ' = function(' + args + '){'); + this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};'); + this.parentIndents++; + this.visit(block); + this.parentIndents--; + this.buf.push('};'); + } + }, + + /** + * Visit `tag` buffering tag markup, generating + * attributes, visiting the `tag`'s code and block. + * + * @param {Tag} tag + * @api public + */ + + visitTag: function(tag){ + this.indents++; + var name = tag.name + , pp = this.pp; + + if (tag.buffer) name = "' + (" + name + ") + '"; + + if (!this.hasCompiledTag) { + if (!this.hasCompiledDoctype && 'html' == name) { + this.visitDoctype(); + } + this.hasCompiledTag = true; + } + + // pretty print + if (pp && !tag.isInline()) + this.prettyIndent(0, true); + + if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) { + this.buffer('<' + name); + this.visitAttributes(tag.attrs); + this.terse + ? this.buffer('>') + : this.buffer('/>'); + } else { + // Optimize attributes buffering + if (tag.attrs.length) { + this.buffer('<' + name); + if (tag.attrs.length) this.visitAttributes(tag.attrs); + this.buffer('>'); + } else { + this.buffer('<' + name + '>'); + } + if (tag.code) this.visitCode(tag.code); + this.escape = 'pre' == tag.name; + this.visit(tag.block); + + // pretty print + if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline()) + this.prettyIndent(0, true); + + this.buffer(''); + } + this.indents--; + }, + + /** + * Visit `filter`, throwing when the filter does not exist. + * + * @param {Filter} filter + * @api public + */ + + visitFilter: function(filter){ + var fn = filters[filter.name]; + + // unknown filter + if (!fn) { + if (filter.isASTFilter) { + throw new Error('unknown ast filter "' + filter.name + ':"'); + } else { + throw new Error('unknown filter ":' + filter.name + '"'); + } + } + + if (filter.isASTFilter) { + this.buf.push(fn(filter.block, this, filter.attrs)); + } else { + var text = filter.block.nodes.map(function(node){ return node.val }).join('\n'); + filter.attrs = filter.attrs || {}; + filter.attrs.filename = this.options.filename; + this.buffer(utils.text(fn(text, filter.attrs))); + } + }, + + /** + * Visit `text` node. + * + * @param {Text} text + * @api public + */ + + visitText: function(text){ + text = utils.text(text.val.replace(/\\/g, '_SLASH_')); + if (this.escape) text = escape(text); + text = text.replace(/_SLASH_/g, '\\\\'); + this.buffer(text); + }, + + /** + * Visit a `comment`, only buffering when the buffer flag is set. + * + * @param {Comment} comment + * @api public + */ + + visitComment: function(comment){ + if (!comment.buffer) return; + if (this.pp) this.prettyIndent(1, true); + this.buffer(''); + }, + + /** + * Visit a `BlockComment`. + * + * @param {Comment} comment + * @api public + */ + + visitBlockComment: function(comment){ + if (!comment.buffer) return; + if (0 == comment.val.trim().indexOf('if')) { + this.buffer(''); + } else { + this.buffer(''); + } + }, + + /** + * Visit `code`, respecting buffer / escape flags. + * If the code is followed by a block, wrap it in + * a self-calling function. + * + * @param {Code} code + * @api public + */ + + visitCode: function(code){ + // Wrap code blocks with {}. + // we only wrap unbuffered code blocks ATM + // since they are usually flow control + + // Buffer code + if (code.buffer) { + var val = code.val.trimLeft(); + this.buf.push('var __val__ = ' + val); + val = 'null == __val__ ? "" : __val__'; + if (code.escape) val = 'escape(' + val + ')'; + this.buf.push("buf.push(" + val + ");"); + } else { + this.buf.push(code.val); + } + + // Block support + if (code.block) { + if (!code.buffer) this.buf.push('{'); + this.visit(code.block); + if (!code.buffer) this.buf.push('}'); + } + }, + + /** + * Visit `each` block. + * + * @param {Each} each + * @api public + */ + + visitEach: function(each){ + this.buf.push('' + + '// iterate ' + each.obj + '\n' + + ';(function(){\n' + + ' if (\'number\' == typeof ' + each.obj + '.length) {\n'); + + if (each.alternative) { + this.buf.push(' if (' + each.obj + '.length) {'); + } + + this.buf.push('' + + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push(' }\n'); + + if (each.alternative) { + this.buf.push(' } else {'); + this.visit(each.alternative); + this.buf.push(' }'); + } + + this.buf.push('' + + ' } else {\n' + + ' var $$l = 0;\n' + + ' for (var ' + each.key + ' in ' + each.obj + ') {\n' + + ' $$l++;' + + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push(' }\n'); + + this.buf.push(' }\n'); + if (each.alternative) { + this.buf.push(' if ($$l === 0) {'); + this.visit(each.alternative); + this.buf.push(' }'); + } + this.buf.push(' }\n}).call(this);\n'); + }, + + /** + * Visit `attrs`. + * + * @param {Array} attrs + * @api public + */ + + visitAttributes: function(attrs){ + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push("buf.push(attrs(merge({ " + val.buf + + " }, attributes), merge(" + val.escaped + ", escaped, true)));"); + } else if (val.constant) { + eval('var buf={' + val.buf + '};'); + this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true); + } else { + this.buf.push("buf.push(attrs({ " + val.buf + " }, " + val.escaped + "));"); + } + }, + + /** + * Compile attributes. + */ + + attrs: function(attrs){ + var buf = [] + , classes = [] + , escaped = {} + , constant = attrs.every(function(attr){ return isConstant(attr.val) }) + , inherits = false; + + if (this.terse) buf.push('terse: true'); + + attrs.forEach(function(attr){ + if (attr.name == 'attributes') return inherits = true; + escaped[attr.name] = attr.escaped; + if (attr.name == 'class') { + classes.push('(' + attr.val + ')'); + } else { + var pair = "'" + attr.name + "':(" + attr.val + ')'; + buf.push(pair); + } + }); + + if (classes.length) { + classes = classes.join(" + ' ' + "); + buf.push("class: " + classes); + } + + return { + buf: buf.join(', ').replace('class:', '"class":'), + escaped: JSON.stringify(escaped), + inherits: inherits, + constant: constant + }; + } +}; + +/** + * Check if expression can be evaluated to a constant + * + * @param {String} expression + * @return {Boolean} + * @api private + */ + +function isConstant(val){ + // Check strings/literals + if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val)) + return true; + + // Check numbers + if (!isNaN(Number(val))) + return true; + + // Check arrays + var matches; + if (matches = /^ *\[(.*)\] *$/.exec(val)) + return matches[1].split(',').every(isConstant); + + return false; +} + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + +}); // module: compiler.js + +require.register("doctypes.js", function(module, exports, require){ + +/*! + * Jade - doctypes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + '5': '' + , 'default': '' + , 'xml': '' + , 'transitional': '' + , 'strict': '' + , 'frameset': '' + , '1.1': '' + , 'basic': '' + , 'mobile': '' +}; +}); // module: doctypes.js + +require.register("filters.js", function(module, exports, require){ + +/*! + * Jade - filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + + /** + * Wrap text with CDATA block. + */ + + cdata: function(str){ + return ''; + }, + + /** + * Transform sass to css, wrapped in style tags. + */ + + sass: function(str){ + str = str.replace(/\\n/g, '\n'); + var sass = require('sass').render(str).replace(/\n/g, '\\n'); + return ''; + }, + + /** + * Transform stylus to css, wrapped in style tags. + */ + + stylus: function(str, options){ + var ret; + str = str.replace(/\\n/g, '\n'); + var stylus = require('stylus'); + stylus(str, options).render(function(err, css){ + if (err) throw err; + ret = css.replace(/\n/g, '\\n'); + }); + return ''; + }, + + /** + * Transform less to css, wrapped in style tags. + */ + + less: function(str){ + var ret; + str = str.replace(/\\n/g, '\n'); + require('less').render(str, function(err, css){ + if (err) throw err; + ret = ''; + }); + return ret; + }, + + /** + * Transform markdown to html. + */ + + markdown: function(str){ + var md; + + // support markdown / discount + try { + md = require('markdown'); + } catch (err){ + try { + md = require('discount'); + } catch (err) { + try { + md = require('markdown-js'); + } catch (err) { + try { + md = require('marked'); + } catch (err) { + throw new + Error('Cannot find markdown library, install markdown, discount, or marked.'); + } + } + } + } + + str = str.replace(/\\n/g, '\n'); + return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,'''); + }, + + /** + * Transform coffeescript to javascript. + */ + + coffeescript: function(str){ + var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); + return ''; + } +}; + +}); // module: filters.js + +require.register("inline-tags.js", function(module, exports, require){ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; +}); // module: inline-tags.js + +require.register("jade.js", function(module, exports, require){ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Parser = require('./parser') + , Lexer = require('./lexer') + , Compiler = require('./compiler') + , runtime = require('./runtime') + +/** + * Library version. + */ + +exports.version = '0.27.6'; + +/** + * Expose self closing tags. + */ + +exports.selfClosing = require('./self-closing'); + +/** + * Default supported doctypes. + */ + +exports.doctypes = require('./doctypes'); + +/** + * Text filters. + */ + +exports.filters = require('./filters'); + +/** + * Utilities. + */ + +exports.utils = require('./utils'); + +/** + * Expose `Compiler`. + */ + +exports.Compiler = Compiler; + +/** + * Expose `Parser`. + */ + +exports.Parser = Parser; + +/** + * Expose `Lexer`. + */ + +exports.Lexer = Lexer; + +/** + * Nodes. + */ + +exports.nodes = require('./nodes'); + +/** + * Jade runtime helpers. + */ + +exports.runtime = runtime; + +/** + * Template function cache. + */ + +exports.cache = {}; + +/** + * Parse the given `str` of jade and return a function body. + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api private + */ + +function parse(str, options){ + try { + // Parse + var parser = new Parser(str, options.filename, options); + + // Compile + var compiler = new (options.compiler || Compiler)(parser.parse(), options) + , js = compiler.compile(); + + // Debug compiler + if (options.debug) { + console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' ')); + } + + return '' + + 'var buf = [];\n' + + (options.self + ? 'var self = locals || {};\n' + js + : 'with (locals || {}) {\n' + js + '\n}\n') + + 'return buf.join("");'; + } catch (err) { + parser = parser.context(); + runtime.rethrow(err, parser.filename, parser.lexer.lineno); + } +} + +/** + * Strip any UTF-8 BOM off of the start of `str`, if it exists. + * + * @param {String} str + * @return {String} + * @api private + */ + +function stripBOM(str){ + return 0xFEFF == str.charCodeAt(0) + ? str.substring(1) + : str; +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + str = stripBOM(String(str)); + + if (options.compileDebug !== false) { + fn = [ + 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(str, options) + , '} catch (err) {' + , ' rethrow(err, __jade[0].filename, __jade[0].lineno);' + , '}' + ].join('\n'); + } else { + fn = parse(str, options); + } + + if (client) { + fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn; + } + + fn = new Function('locals, attrs, escape, rethrow, merge', fn); + + if (client) return fn; + + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge); + }; +}; + +/** + * Render the given `str` of jade and invoke + * the callback `fn(err, str)`. + * + * Options: + * + * - `cache` enable template caching + * - `filename` filename required for `include` / `extends` and caching + * + * @param {String} str + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +exports.render = function(str, options, fn){ + // swap args + if ('function' == typeof options) { + fn = options, options = {}; + } + + // cache requires .filename + if (options.cache && !options.filename) { + return fn(new Error('the "filename" option is required for caching')); + } + + try { + var path = options.filename; + var tmpl = options.cache + ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options)) + : exports.compile(str, options); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Render a Jade file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + try { + options.filename = path; + var str = options.cache + ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8')) + : fs.readFileSync(path, 'utf8'); + exports.render(str, options, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Express support. + */ + +exports.__express = exports.renderFile; + +}); // module: jade.js + +require.register("lexer.js", function(module, exports, require){ +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +var utils = require('./utils'); + +/** + * Initialize `Lexer` with the given `str`. + * + * Options: + * + * - `colons` allow colons for attr delimiters + * + * @param {String} str + * @param {Object} options + * @api private + */ + +var Lexer = module.exports = function Lexer(str, options) { + options = options || {}; + this.input = str.replace(/\r\n|\r/g, '\n'); + this.colons = options.colons; + this.deferredTokens = []; + this.lastIndents = 0; + this.lineno = 1; + this.stash = []; + this.indentStack = []; + this.indentRe = null; + this.pipeless = false; +}; + +/** + * Lexer prototype. + */ + +Lexer.prototype = { + + /** + * Construct a token with the given `type` and `val`. + * + * @param {String} type + * @param {String} val + * @return {Object} + * @api private + */ + + tok: function(type, val){ + return { + type: type + , line: this.lineno + , val: val + } + }, + + /** + * Consume the given `len` of input. + * + * @param {Number} len + * @api private + */ + + consume: function(len){ + this.input = this.input.substr(len); + }, + + /** + * Scan for `type` with the given `regexp`. + * + * @param {String} type + * @param {RegExp} regexp + * @return {Object} + * @api private + */ + + scan: function(regexp, type){ + var captures; + if (captures = regexp.exec(this.input)) { + this.consume(captures[0].length); + return this.tok(type, captures[1]); + } + }, + + /** + * Defer the given `tok`. + * + * @param {Object} tok + * @api private + */ + + defer: function(tok){ + this.deferredTokens.push(tok); + }, + + /** + * 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.next()); + return this.stash[--n]; + }, + + /** + * Return the indexOf `start` / `end` delimiters. + * + * @param {String} start + * @param {String} end + * @return {Number} + * @api private + */ + + indexOfDelimiters: function(start, end){ + var str = this.input + , nstart = 0 + , nend = 0 + , pos = 0; + for (var i = 0, len = str.length; i < len; ++i) { + if (start == str.charAt(i)) { + ++nstart; + } else if (end == str.charAt(i)) { + if (++nend == nstart) { + pos = i; + break; + } + } + } + return pos; + }, + + /** + * Stashed token. + */ + + stashed: function() { + return this.stash.length + && this.stash.shift(); + }, + + /** + * Deferred token. + */ + + deferred: function() { + return this.deferredTokens.length + && this.deferredTokens.shift(); + }, + + /** + * end-of-source. + */ + + eos: function() { + if (this.input.length) return; + if (this.indentStack.length) { + this.indentStack.shift(); + return this.tok('outdent'); + } else { + return this.tok('eos'); + } + }, + + /** + * Blank line. + */ + + blank: function() { + var captures; + if (captures = /^\n *\n/.exec(this.input)) { + this.consume(captures[0].length - 1); + + ++this.lineno; + if (this.pipeless) return this.tok('text', ''); + return this.next(); + } + }, + + /** + * Comment. + */ + + comment: function() { + var captures; + if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('comment', captures[2]); + tok.buffer = '-' != captures[1]; + return tok; + } + }, + + /** + * Interpolated tag. + */ + + interpolation: function() { + var captures; + if (captures = /^#\{(.*?)\}/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('interpolation', captures[1]); + } + }, + + /** + * Tag. + */ + + tag: function() { + var captures; + if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) { + this.consume(captures[0].length); + var tok, name = captures[1]; + if (':' == name[name.length - 1]) { + name = name.slice(0, -1); + tok = this.tok('tag', name); + this.defer(this.tok(':')); + while (' ' == this.input[0]) this.input = this.input.substr(1); + } else { + tok = this.tok('tag', name); + } + tok.selfClosing = !! captures[2]; + return tok; + } + }, + + /** + * Filter. + */ + + filter: function() { + return this.scan(/^:(\w+)/, 'filter'); + }, + + /** + * Doctype. + */ + + doctype: function() { + return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype'); + }, + + /** + * Id. + */ + + id: function() { + return this.scan(/^#([\w-]+)/, 'id'); + }, + + /** + * Class. + */ + + className: function() { + return this.scan(/^\.([\w-]+)/, 'class'); + }, + + /** + * Text. + */ + + text: function() { + return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text'); + }, + + /** + * Extends. + */ + + "extends": function() { + return this.scan(/^extends? +([^\n]+)/, 'extends'); + }, + + /** + * Block prepend. + */ + + prepend: function() { + var captures; + if (captures = /^prepend +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'prepend' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block append. + */ + + append: function() { + var captures; + if (captures = /^append +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'append' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block. + */ + + block: function() { + var captures; + if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = captures[1] || 'replace' + , name = captures[2] + , tok = this.tok('block', name); + + tok.mode = mode; + return tok; + } + }, + + /** + * Yield. + */ + + yield: function() { + return this.scan(/^yield */, 'yield'); + }, + + /** + * Include. + */ + + include: function() { + return this.scan(/^include +([^\n]+)/, 'include'); + }, + + /** + * Case. + */ + + "case": function() { + return this.scan(/^case +([^\n]+)/, 'case'); + }, + + /** + * When. + */ + + when: function() { + return this.scan(/^when +([^:\n]+)/, 'when'); + }, + + /** + * Default. + */ + + "default": function() { + return this.scan(/^default */, 'default'); + }, + + /** + * Assignment. + */ + + assignment: function() { + var captures; + if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) { + this.consume(captures[0].length); + var name = captures[1] + , val = captures[2]; + return this.tok('code', 'var ' + name + ' = (' + val + ');'); + } + }, + + /** + * Call mixin. + */ + + call: function(){ + var captures; + if (captures = /^\+([-\w]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('call', captures[1]); + + // Check for args (not attributes) + if (captures = /^ *\((.*?)\)/.exec(this.input)) { + if (!/^ *[-\w]+ *=/.test(captures[1])) { + this.consume(captures[0].length); + tok.args = captures[1]; + } + } + + return tok; + } + }, + + /** + * Mixin. + */ + + mixin: function(){ + var captures; + if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('mixin', captures[1]); + tok.args = captures[2]; + return tok; + } + }, + + /** + * Conditional. + */ + + conditional: function() { + var captures; + if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var type = captures[1] + , js = captures[2]; + + switch (type) { + case 'if': js = 'if (' + js + ')'; break; + case 'unless': js = 'if (!(' + js + '))'; break; + case 'else if': js = 'else if (' + js + ')'; break; + case 'else': js = 'else'; break; + } + + return this.tok('code', js); + } + }, + + /** + * While. + */ + + "while": function() { + var captures; + if (captures = /^while +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('code', 'while (' + captures[1] + ')'); + } + }, + + /** + * Each. + */ + + each: function() { + var captures; + if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('each', captures[1]); + tok.key = captures[2] || '$index'; + tok.code = captures[3]; + return tok; + } + }, + + /** + * Code. + */ + + code: function() { + var captures; + if (captures = /^(!?=|-)([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var flags = captures[1]; + captures[1] = captures[2]; + var tok = this.tok('code', captures[1]); + tok.escape = flags.charAt(0) === '='; + tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.indexOfDelimiters('(', ')') + , str = this.input.substr(1, index-1) + , tok = this.tok('attrs') + , len = str.length + , colons = this.colons + , states = ['key'] + , escapedAttr + , key = '' + , val = '' + , quote + , c + , p; + + function state(){ + return states[states.length - 1]; + } + + function interpolate(attr) { + return attr.replace(/(\\)?#\{([^}]+)\}/g, function(_, escape, expr){ + return escape + ? _ + : quote + " + (" + expr + ") + " + quote; + }); + } + + this.consume(index + 1); + tok.attrs = {}; + tok.escaped = {}; + + function parse(c) { + var real = c; + // TODO: remove when people fix ":" + if (colons && ':' == c) c = '='; + switch (c) { + case ',': + case '\n': + switch (state()) { + case 'expr': + case 'array': + case 'string': + case 'object': + val += c; + break; + default: + states.push('key'); + val = val.trim(); + key = key.trim(); + if ('' == key) return; + key = key.replace(/^['"]|['"]$/g, '').replace('!', ''); + tok.escaped[key] = escapedAttr; + tok.attrs[key] = '' == val + ? true + : interpolate(val); + key = val = ''; + } + break; + case '=': + switch (state()) { + case 'key char': + key += real; + break; + case 'val': + case 'expr': + case 'array': + case 'string': + case 'object': + val += real; + break; + default: + escapedAttr = '!' != p; + states.push('val'); + } + break; + case '(': + if ('val' == state() + || 'expr' == state()) states.push('expr'); + val += c; + break; + case ')': + if ('expr' == state() + || 'val' == state()) states.pop(); + val += c; + break; + case '{': + if ('val' == state()) states.push('object'); + val += c; + break; + case '}': + if ('object' == state()) states.pop(); + val += c; + break; + case '[': + if ('val' == state()) states.push('array'); + val += c; + break; + case ']': + if ('array' == state()) states.pop(); + val += c; + break; + case '"': + case "'": + switch (state()) { + case 'key': + states.push('key char'); + break; + case 'key char': + states.pop(); + break; + case 'string': + if (c == quote) states.pop(); + val += c; + break; + default: + states.push('string'); + val += c; + quote = c; + } + break; + case '': + break; + default: + switch (state()) { + case 'key': + case 'key char': + key += c; + break; + default: + val += c; + } + } + p = c; + } + + for (var i = 0; i < len; ++i) { + parse(str.charAt(i)); + } + + parse(','); + + if ('/' == this.input.charAt(0)) { + this.consume(1); + tok.selfClosing = true; + } + + return tok; + } + }, + + /** + * Indent | Outdent | Newline. + */ + + indent: function() { + var captures, re; + + // established regexp + if (this.indentRe) { + captures = this.indentRe.exec(this.input); + // determine regexp + } else { + // tabs + re = /^\n(\t*) */; + captures = re.exec(this.input); + + // spaces + if (captures && !captures[1].length) { + re = /^\n( *)/; + captures = re.exec(this.input); + } + + // established + if (captures && captures[1].length) this.indentRe = re; + } + + if (captures) { + var tok + , indents = captures[1].length; + + ++this.lineno; + this.consume(indents + 1); + + if (' ' == this.input[0] || '\t' == this.input[0]) { + throw new Error('Invalid indentation, you can use tabs or spaces but not both'); + } + + // blank line + if ('\n' == this.input[0]) return this.tok('newline'); + + // outdent + if (this.indentStack.length && indents < this.indentStack[0]) { + while (this.indentStack.length && this.indentStack[0] > indents) { + this.stash.push(this.tok('outdent')); + this.indentStack.shift(); + } + tok = this.stash.pop(); + // indent + } else if (indents && indents != this.indentStack[0]) { + this.indentStack.unshift(indents); + tok = this.tok('indent', indents); + // newline + } else { + tok = this.tok('newline'); + } + + return tok; + } + }, + + /** + * Pipe-less text consumed only when + * pipeless is true; + */ + + pipelessText: function() { + if (this.pipeless) { + if ('\n' == this.input[0]) return; + var i = this.input.indexOf('\n'); + if (-1 == i) i = this.input.length; + var str = this.input.substr(0, i); + this.consume(str.length); + return this.tok('text', str); + } + }, + + /** + * ':' + */ + + colon: function() { + return this.scan(/^: */, ':'); + }, + + /** + * Return the next token object, or those + * previously stashed by lookahead. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.stashed() + || this.next(); + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + next: function() { + return this.deferred() + || this.blank() + || this.eos() + || this.pipelessText() + || this.yield() + || this.doctype() + || this.interpolation() + || this["case"]() + || this.when() + || this["default"]() + || this["extends"]() + || this.append() + || this.prepend() + || this.block() + || this.include() + || this.mixin() + || this.call() + || this.conditional() + || this.each() + || this["while"]() + || this.assignment() + || this.tag() + || this.filter() + || this.code() + || this.id() + || this.className() + || this.attrs() + || this.indent() + || this.comment() + || this.colon() + || this.text(); + } +}; + +}); // module: lexer.js + +require.register("nodes/attrs.js", function(module, exports, require){ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'), + Block = require('./block'); + +/** + * Initialize a `Attrs` node. + * + * @api public + */ + +var Attrs = module.exports = function Attrs() { + this.attrs = []; +}; + +/** + * Inherit from `Node`. + */ + +Attrs.prototype = new Node; +Attrs.prototype.constructor = Attrs; + + +/** + * Set attribute `name` to `val`, keep in mind these become + * part of a raw js object literal, so to quote a value you must + * '"quote me"', otherwise or example 'user.name' is literal JavaScript. + * + * @param {String} name + * @param {String} val + * @param {Boolean} escaped + * @return {Tag} for chaining + * @api public + */ + +Attrs.prototype.setAttribute = function(name, val, escaped){ + this.attrs.push({ name: name, val: val, escaped: escaped }); + return this; +}; + +/** + * Remove attribute `name` when present. + * + * @param {String} name + * @api public + */ + +Attrs.prototype.removeAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + delete this.attrs[i]; + } + } +}; + +/** + * Get attribute value by `name`. + * + * @param {String} name + * @return {String} + * @api public + */ + +Attrs.prototype.getAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + return this.attrs[i].val; + } + } +}; + +}); // module: nodes/attrs.js + +require.register("nodes/block-comment.js", function(module, exports, require){ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `BlockComment` with the given `block`. + * + * @param {String} val + * @param {Block} block + * @param {Boolean} buffer + * @api public + */ + +var BlockComment = module.exports = function BlockComment(val, block, buffer) { + this.block = block; + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +BlockComment.prototype = new Node; +BlockComment.prototype.constructor = BlockComment; + +}); // module: nodes/block-comment.js + +require.register("nodes/block.js", function(module, exports, require){ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Block` with an optional `node`. + * + * @param {Node} node + * @api public + */ + +var Block = module.exports = function Block(node){ + this.nodes = []; + if (node) this.push(node); +}; + +/** + * Inherit from `Node`. + */ + +Block.prototype = new Node; +Block.prototype.constructor = Block; + + +/** + * Block flag. + */ + +Block.prototype.isBlock = true; + +/** + * Replace the nodes in `other` with the nodes + * in `this` block. + * + * @param {Block} other + * @api private + */ + +Block.prototype.replace = function(other){ + other.nodes = this.nodes; +}; + +/** + * Pust the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.push = function(node){ + return this.nodes.push(node); +}; + +/** + * Check if this block is empty. + * + * @return {Boolean} + * @api public + */ + +Block.prototype.isEmpty = function(){ + return 0 == this.nodes.length; +}; + +/** + * Unshift the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.unshift = function(node){ + return this.nodes.unshift(node); +}; + +/** + * Return the "last" block, or the first `yield` node. + * + * @return {Block} + * @api private + */ + +Block.prototype.includeBlock = function(){ + var ret = this + , node; + + for (var i = 0, len = this.nodes.length; i < len; ++i) { + node = this.nodes[i]; + if (node.yield) return node; + else if (node.textOnly) continue; + else if (node.includeBlock) ret = node.includeBlock(); + else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock(); + if (ret.yield) return ret; + } + + return ret; +}; + +/** + * Return a clone of this block. + * + * @return {Block} + * @api private + */ + +Block.prototype.clone = function(){ + var clone = new Block; + for (var i = 0, len = this.nodes.length; i < len; ++i) { + clone.push(this.nodes[i].clone()); + } + return clone; +}; + + +}); // module: nodes/block.js + +require.register("nodes/case.js", function(module, exports, require){ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Case` with `expr`. + * + * @param {String} expr + * @api public + */ + +var Case = exports = module.exports = function Case(expr, block){ + this.expr = expr; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Case.prototype = new Node; +Case.prototype.constructor = Case; + + +var When = exports.When = function When(expr, block){ + this.expr = expr; + this.block = block; + this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +When.prototype = new Node; +When.prototype.constructor = When; + + + +}); // module: nodes/case.js + +require.register("nodes/code.js", function(module, exports, require){ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Code` node with the given code `val`. + * Code may also be optionally buffered and escaped. + * + * @param {String} val + * @param {Boolean} buffer + * @param {Boolean} escape + * @api public + */ + +var Code = module.exports = function Code(val, buffer, escape) { + this.val = val; + this.buffer = buffer; + this.escape = escape; + if (val.match(/^ *else/)) this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +Code.prototype = new Node; +Code.prototype.constructor = Code; + +}); // module: nodes/code.js + +require.register("nodes/comment.js", function(module, exports, require){ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Comment` with the given `val`, optionally `buffer`, + * otherwise the comment may render in the output. + * + * @param {String} val + * @param {Boolean} buffer + * @api public + */ + +var Comment = module.exports = function Comment(val, buffer) { + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +Comment.prototype = new Node; +Comment.prototype.constructor = Comment; + +}); // module: nodes/comment.js + +require.register("nodes/doctype.js", function(module, exports, require){ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Doctype` with the given `val`. + * + * @param {String} val + * @api public + */ + +var Doctype = module.exports = function Doctype(val) { + this.val = val; +}; + +/** + * Inherit from `Node`. + */ + +Doctype.prototype = new Node; +Doctype.prototype.constructor = Doctype; + +}); // module: nodes/doctype.js + +require.register("nodes/each.js", function(module, exports, require){ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize an `Each` node, representing iteration + * + * @param {String} obj + * @param {String} val + * @param {String} key + * @param {Block} block + * @api public + */ + +var Each = module.exports = function Each(obj, val, key, block) { + this.obj = obj; + this.val = val; + this.key = key; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Each.prototype = new Node; +Each.prototype.constructor = Each; + +}); // module: nodes/each.js + +require.register("nodes/filter.js", function(module, exports, require){ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node') + , Block = require('./block'); + +/** + * Initialize a `Filter` node with the given + * filter `name` and `block`. + * + * @param {String} name + * @param {Block|Node} block + * @api public + */ + +var Filter = module.exports = function Filter(name, block, attrs) { + this.name = name; + this.block = block; + this.attrs = attrs; + this.isASTFilter = !block.nodes.every(function(node){ return node.isText }); +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype = new Node; +Filter.prototype.constructor = Filter; + +}); // module: nodes/filter.js + +require.register("nodes/index.js", function(module, exports, require){ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +exports.Node = require('./node'); +exports.Tag = require('./tag'); +exports.Code = require('./code'); +exports.Each = require('./each'); +exports.Case = require('./case'); +exports.Text = require('./text'); +exports.Block = require('./block'); +exports.Mixin = require('./mixin'); +exports.Filter = require('./filter'); +exports.Comment = require('./comment'); +exports.Literal = require('./literal'); +exports.BlockComment = require('./block-comment'); +exports.Doctype = require('./doctype'); + +}); // module: nodes/index.js + +require.register("nodes/literal.js", function(module, exports, require){ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Literal` node with the given `str. + * + * @param {String} str + * @api public + */ + +var Literal = module.exports = function Literal(str) { + this.str = str + .replace(/\\/g, "\\\\") + .replace(/\n|\r\n/g, "\\n") + .replace(/'/g, "\\'"); +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype = new Node; +Literal.prototype.constructor = Literal; + + +}); // module: nodes/literal.js + +require.register("nodes/mixin.js", function(module, exports, require){ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'); + +/** + * Initialize a new `Mixin` with `name` and `block`. + * + * @param {String} name + * @param {String} args + * @param {Block} block + * @api public + */ + +var Mixin = module.exports = function Mixin(name, args, block, call){ + this.name = name; + this.args = args; + this.block = block; + this.attrs = []; + this.call = call; +}; + +/** + * Inherit from `Attrs`. + */ + +Mixin.prototype = new Attrs; +Mixin.prototype.constructor = Mixin; + + + +}); // module: nodes/mixin.js + +require.register("nodes/node.js", function(module, exports, require){ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize a `Node`. + * + * @api public + */ + +var Node = module.exports = function Node(){}; + +/** + * Clone this node (return itself) + * + * @return {Node} + * @api private + */ + +Node.prototype.clone = function(){ + return this; +}; + +}); // module: nodes/node.js + +require.register("nodes/tag.js", function(module, exports, require){ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'), + Block = require('./block'), + inlineTags = require('../inline-tags'); + +/** + * Initialize a `Tag` node with the given tag `name` and optional `block`. + * + * @param {String} name + * @param {Block} block + * @api public + */ + +var Tag = module.exports = function Tag(name, block) { + this.name = name; + this.attrs = []; + this.block = block || new Block; +}; + +/** + * Inherit from `Attrs`. + */ + +Tag.prototype = new Attrs; +Tag.prototype.constructor = Tag; + + +/** + * Clone this tag. + * + * @return {Tag} + * @api private + */ + +Tag.prototype.clone = function(){ + var clone = new Tag(this.name, this.block.clone()); + clone.line = this.line; + clone.attrs = this.attrs; + clone.textOnly = this.textOnly; + return clone; +}; + +/** + * Check if this tag is an inline tag. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.isInline = function(){ + return ~inlineTags.indexOf(this.name); +}; + +/** + * Check if this tag's contents can be inlined. Used for pretty printing. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.canInline = function(){ + var nodes = this.block.nodes; + + function isInline(node){ + // Recurse if the node is a block + if (node.isBlock) return node.nodes.every(isInline); + return node.isText || (node.isInline && node.isInline()); + } + + // Empty tag + if (!nodes.length) return true; + + // Text-only or inline-only tag + if (1 == nodes.length) return isInline(nodes[0]); + + // Multi-line inline-only tag + if (this.block.nodes.every(isInline)) { + for (var i = 1, len = nodes.length; i < len; ++i) { + if (nodes[i-1].isText && nodes[i].isText) + return false; + } + return true; + } + + // Mixed tag + return false; +}; +}); // module: nodes/tag.js + +require.register("nodes/text.js", function(module, exports, require){ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Text` node with optional `line`. + * + * @param {String} line + * @api public + */ + +var Text = module.exports = function Text(line) { + this.val = ''; + if ('string' == typeof line) this.val = line; +}; + +/** + * Inherit from `Node`. + */ + +Text.prototype = new Node; +Text.prototype.constructor = Text; + + +/** + * Flag as text. + */ + +Text.prototype.isText = true; +}); // module: nodes/text.js + +require.register("parser.js", function(module, exports, require){ + +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes') + , utils = require('./utils'); + +/** + * Initialize `Parser` with the given input `str` and `filename`. + * + * @param {String} str + * @param {String} filename + * @param {Object} options + * @api public + */ + +var Parser = exports = module.exports = function Parser(str, filename, options){ + this.input = str; + this.lexer = new Lexer(str, options); + this.filename = filename; + this.blocks = {}; + this.mixins = {}; + this.options = options; + this.contexts = [this]; +}; + +/** + * Tags that may not contain tags. + */ + +var textOnly = exports.textOnly = ['script', 'style']; + +/** + * Parser prototype. + */ + +Parser.prototype = { + + /** + * Push `parser` onto the context stack, + * or pop and return a `Parser`. + */ + + context: function(parser){ + if (parser) { + this.contexts.push(parser); + } else { + return this.contexts.pop(); + } + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.lexer.advance(); + }, + + /** + * Skip `n` tokens. + * + * @param {Number} n + * @api private + */ + + skip: function(n){ + while (n--) this.advance(); + }, + + /** + * Single token lookahead. + * + * @return {Object} + * @api private + */ + + peek: function() { + return this.lookahead(1); + }, + + /** + * Return lexer lineno. + * + * @return {Number} + * @api private + */ + + line: function() { + return this.lexer.lineno; + }, + + /** + * `n` token lookahead. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + return this.lexer.lookahead(n); + }, + + /** + * Parse input returning a string of js for evaluation. + * + * @return {String} + * @api public + */ + + parse: function(){ + var block = new nodes.Block, parser; + block.line = this.line(); + + while ('eos' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + + if (parser = this.extending) { + this.context(parser); + var ast = parser.parse(); + this.context(); + // hoist mixins + for (var name in this.mixins) + ast.unshift(this.mixins[name]); + return ast; + } + + return block; + }, + + /** + * Expect the given type, or throw an exception. + * + * @param {String} type + * @api private + */ + + expect: function(type){ + if (this.peek().type === type) { + return this.advance(); + } else { + throw new Error('expected "' + type + '", but got "' + this.peek().type + '"'); + } + }, + + /** + * Accept the given `type`. + * + * @param {String} type + * @api private + */ + + accept: function(type){ + if (this.peek().type === type) { + return this.advance(); + } + }, + + /** + * tag + * | doctype + * | mixin + * | include + * | filter + * | comment + * | text + * | each + * | code + * | yield + * | id + * | class + * | interpolation + */ + + parseExpr: function(){ + switch (this.peek().type) { + case 'tag': + return this.parseTag(); + case 'mixin': + return this.parseMixin(); + case 'block': + return this.parseBlock(); + case 'case': + return this.parseCase(); + case 'when': + return this.parseWhen(); + case 'default': + return this.parseDefault(); + case 'extends': + return this.parseExtends(); + case 'include': + return this.parseInclude(); + case 'doctype': + return this.parseDoctype(); + case 'filter': + return this.parseFilter(); + case 'comment': + return this.parseComment(); + case 'text': + return this.parseText(); + case 'each': + return this.parseEach(); + case 'code': + return this.parseCode(); + case 'call': + return this.parseCall(); + case 'interpolation': + return this.parseInterpolation(); + case 'yield': + this.advance(); + var block = new nodes.Block; + block.yield = true; + return block; + case 'id': + case 'class': + var tok = this.advance(); + this.lexer.defer(this.lexer.tok('tag', 'div')); + this.lexer.defer(tok); + return this.parseExpr(); + default: + throw new Error('unexpected token "' + this.peek().type + '"'); + } + }, + + /** + * Text + */ + + parseText: function(){ + var tok = this.expect('text') + , node = new nodes.Text(tok.val); + node.line = this.line(); + return node; + }, + + /** + * ':' expr + * | block + */ + + parseBlockExpansion: function(){ + if (':' == this.peek().type) { + this.advance(); + return new nodes.Block(this.parseExpr()); + } else { + return this.block(); + } + }, + + /** + * case + */ + + parseCase: function(){ + var val = this.expect('case').val + , node = new nodes.Case(val); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * when + */ + + parseWhen: function(){ + var val = this.expect('when').val + return new nodes.Case.When(val, this.parseBlockExpansion()); + }, + + /** + * default + */ + + parseDefault: function(){ + this.expect('default'); + return new nodes.Case.When('default', this.parseBlockExpansion()); + }, + + /** + * code + */ + + parseCode: function(){ + var tok = this.expect('code') + , node = new nodes.Code(tok.val, tok.buffer, tok.escape) + , block + , i = 1; + node.line = this.line(); + while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; + block = 'indent' == this.lookahead(i).type; + if (block) { + this.skip(i-1); + node.block = this.block(); + } + return node; + }, + + /** + * comment + */ + + parseComment: function(){ + var tok = this.expect('comment') + , node; + + if ('indent' == this.peek().type) { + node = new nodes.BlockComment(tok.val, this.block(), tok.buffer); + } else { + node = new nodes.Comment(tok.val, tok.buffer); + } + + node.line = this.line(); + return node; + }, + + /** + * doctype + */ + + parseDoctype: function(){ + var tok = this.expect('doctype') + , node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var block + , tok = this.expect('filter') + , attrs = this.accept('attrs'); + + this.lexer.pipeless = true; + block = this.parseTextBlock(); + this.lexer.pipeless = false; + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * tag ':' attrs? block + */ + + parseASTFilter: function(){ + var block + , tok = this.expect('tag') + , attrs = this.accept('attrs'); + + this.expect(':'); + block = this.block(); + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * each block + */ + + parseEach: function(){ + var tok = this.expect('each') + , node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + if (this.peek().type == 'code' && this.peek().val == 'else') { + this.advance(); + node.alternative = this.block(); + } + return node; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + if (!this.filename) + throw new Error('the "filename" option is required to extend templates'); + + var path = this.expect('extends').val.trim() + , dir = dirname(this.filename); + + var path = join(dir, path + '.jade') + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block') + , mode = block.mode + , name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name]; + + if (prev) { + switch (prev.mode) { + case 'append': + block.nodes = block.nodes.concat(prev.nodes); + prev = block; + break; + case 'prepend': + block.nodes = prev.nodes.concat(block.nodes); + prev = block; + break; + } + } + + block.mode = mode; + return this.blocks[name] = prev || block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + var path = this.expect('include').val.trim() + , dir = dirname(this.filename); + + if (!this.filename) + throw new Error('the "filename" option is required to use includes'); + + // no extension + if (!~basename(path).indexOf('.')) { + path += '.jade'; + } + + // non-jade + if ('.jade' != path.substr(-5)) { + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8'); + return new nodes.Literal(str); + } + + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + parser.blocks = utils.merge({}, this.blocks); + parser.mixins = this.mixins; + + this.context(parser); + var ast = parser.parse(); + this.context(); + ast.filename = path; + + if ('indent' == this.peek().type) { + ast.includeBlock().push(this.block()); + } + + return ast; + }, + + /** + * call ident block + */ + + parseCall: function(){ + var tok = this.expect('call') + , name = tok.val + , args = tok.args + , mixin = new nodes.Mixin(name, args, new nodes.Block, true); + + this.tag(mixin); + if (mixin.block.isEmpty()) mixin.block = null; + return mixin; + }, + + /** + * mixin block + */ + + parseMixin: function(){ + var tok = this.expect('mixin') + , name = tok.val + , args = tok.args + , mixin; + + // definition + if ('indent' == this.peek().type) { + mixin = new nodes.Mixin(name, args, this.block(), false); + this.mixins[name] = mixin; + return mixin; + // call + } else { + return new nodes.Mixin(name, args, null, true); + } + }, + + /** + * indent (text | newline)* outdent + */ + + parseTextBlock: function(){ + var block = new nodes.Block; + block.line = this.line(); + var spaces = this.expect('indent').val; + if (null == this._spaces) this._spaces = spaces; + var indent = Array(spaces - this._spaces + 1).join(' '); + while ('outdent' != this.peek().type) { + switch (this.peek().type) { + case 'newline': + this.advance(); + break; + case 'indent': + this.parseTextBlock().nodes.forEach(function(node){ + block.push(node); + }); + break; + default: + var text = new nodes.Text(indent + this.advance().val); + text.line = this.line(); + block.push(text); + } + } + + if (spaces == this._spaces) this._spaces = null; + this.expect('outdent'); + return block; + }, + + /** + * indent expr* outdent + */ + + block: function(){ + var block = new nodes.Block; + block.line = this.line(); + this.expect('indent'); + while ('outdent' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + this.expect('outdent'); + return block; + }, + + /** + * interpolation (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseInterpolation: function(){ + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + tag.buffer = true; + return this.tag(tag); + }, + + /** + * tag (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseTag: function(){ + // ast-filter look-ahead + var i = 2; + if ('attrs' == this.lookahead(i).type) ++i; + if (':' == this.lookahead(i).type) { + if ('indent' == this.lookahead(++i).type) { + return this.parseASTFilter(); + } + } + + var tok = this.advance() + , tag = new nodes.Tag(tok.val); + + tag.selfClosing = tok.selfClosing; + + return this.tag(tag); + }, + + /** + * Parse tag. + */ + + tag: function(tag){ + var dot; + + tag.line = this.line(); + + // (attrs | class | id)* + out: + while (true) { + switch (this.peek().type) { + case 'id': + case 'class': + var tok = this.advance(); + tag.setAttribute(tok.type, "'" + tok.val + "'"); + continue; + case 'attrs': + var tok = this.advance() + , obj = tok.attrs + , escaped = tok.escaped + , names = Object.keys(obj); + + if (tok.selfClosing) tag.selfClosing = true; + + for (var i = 0, len = names.length; i < len; ++i) { + var name = names[i] + , val = obj[name]; + tag.setAttribute(name, val, escaped[name]); + } + continue; + default: + break out; + } + } + + // check immediate '.' + if ('.' == this.peek().val) { + dot = tag.textOnly = true; + this.advance(); + } + + // (text | code | ':')? + switch (this.peek().type) { + case 'text': + tag.block.push(this.parseText()); + break; + case 'code': + tag.code = this.parseCode(); + break; + case ':': + this.advance(); + tag.block = new nodes.Block; + tag.block.push(this.parseExpr()); + break; + } + + // newline* + while ('newline' == this.peek().type) this.advance(); + + tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name); + + // script special-case + if ('script' == tag.name) { + var type = tag.getAttribute('type'); + if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { + tag.textOnly = false; + } + } + + // block? + if ('indent' == this.peek().type) { + if (tag.textOnly) { + this.lexer.pipeless = true; + tag.block = this.parseTextBlock(); + this.lexer.pipeless = false; + } else { + var block = this.block(); + if (tag.block) { + for (var i = 0, len = block.nodes.length; i < len; ++i) { + tag.block.push(block.nodes[i]); + } + } else { + tag.block = block; + } + } + } + + return tag; + } +}; + +}); // module: parser.js + +require.register("runtime.js", function(module, exports, require){ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + ac = ac.filter(nulls); + bc = bc.filter(nulls); + a['class'] = ac.concat(bc).join(' '); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function nulls(val) { + return val != null; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!(\w+|\#\d+);)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno){ + if (!filename) throw err; + + var context = 3 + , str = require('fs').readFileSync(filename, 'utf8') + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; + +}); // module: runtime.js + +require.register("self-closing.js", function(module, exports, require){ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; +}); // module: self-closing.js + +require.register("utils.js", function(module, exports, require){ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Convert interpolation in the given string to JavaScript. + * + * @param {String} str + * @return {String} + * @api private + */ + +var interpolate = exports.interpolate = function(str){ + return str.replace(/(_SLASH_)?([#!]){(.*?)}/g, function(str, escape, flag, code){ + code = code + .replace(/\\'/g, "'") + .replace(/_SLASH_/g, '\\'); + + return escape + ? str.slice(7) + : "' + " + + ('!' == flag ? '' : 'escape') + + "((interp = " + code + + ") == null ? '' : interp) + '"; + }); +}; + +/** + * Escape single quotes in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +var escape = exports.escape = function(str) { + return str.replace(/'/g, "\\'"); +}; + +/** + * Interpolate, and escape the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.text = function(str){ + return interpolate(escape(str)); +}; + +/** + * Merge `b` into `a`. + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api public + */ + +exports.merge = function(a, b) { + for (var key in b) a[key] = b[key]; + return a; +}; + + +}); // module: utils.js + +window.jade = require("jade"); +})(); diff --git a/node_modules/jade/jade.md b/node_modules/jade/jade.md new file mode 100644 index 0000000..051dc03 --- /dev/null +++ b/node_modules/jade/jade.md @@ -0,0 +1,510 @@ + +# Jade + + The jade template engine for node.js + +## Synopsis + + jade [-h|--help] [-v|--version] [-o|--obj STR] + [-O|--out DIR] [-p|--path PATH] [-P|--pretty] + [-c|--client] [-D|--no-debug] + +## Examples + + translate jade the templates dir + + $ jade templates + + create {foo,bar}.html + + $ jade {foo,bar}.jade + + jade over stdio + + $ jade < my.jade > my.html + + jade over s + + $ echo "h1 Jade!" | jade + + foo, bar dirs rendering to /tmp + + $ jade foo bar --out /tmp + + compile client-side templates without debugging + instrumentation, making the output javascript + very light-weight. This requires runtime.js + in your projects. + + $ jade --client --no-debug < my.jade + +## Tags + + Tags are simply nested via whitespace, closing + tags defined for you. These indents are called "blocks". + + ul + li + a Foo + li + a Bar + + You may have several tags in one "block": + + ul + li + a Foo + a Bar + a Baz + +## Self-closing Tags + + Some tags are flagged as self-closing by default, such + as `meta`, `link`, and so on. To explicitly self-close + a tag simply append the `/` character: + + foo/ + foo(bar='baz')/ + + Would yield: + + + + +## Attributes + + Tag attributes look similar to HTML, however + the values are regular JavaScript, here are + some examples: + + a(href='google.com') Google + a(class='button', href='google.com') Google + + As mentioned the attribute values are just JavaScript, + this means ternary operations and other JavaScript expressions + work just fine: + + body(class=user.authenticated ? 'authenticated' : 'anonymous') + a(href=user.website || 'http://google.com') + + Multiple lines work too: + + input(type='checkbox', + name='agreement', + checked) + + Multiple lines without the comma work fine: + + input(type='checkbox' + name='agreement' + checked) + + Funky whitespace? fine: + + input( + type='checkbox' + name='agreement' + checked) + +## Boolean attributes + + Boolean attributes are mirrored by Jade, and accept + bools, aka _true_ or _false_. When no value is specified + _true_ is assumed. For example: + + input(type="checkbox", checked) + // => "" + + For example if the checkbox was for an agreement, perhaps `user.agreed` + was _true_ the following would also output 'checked="checked"': + + input(type="checkbox", checked=user.agreed) + +## Class attributes + + The _class_ attribute accepts an array of classes, + this can be handy when generated from a javascript + function etc: + + classes = ['foo', 'bar', 'baz'] + a(class=classes) + // => "" + +## Class literal + + Classes may be defined using a ".CLASSNAME" syntax: + + .button + // => "
    " + + Or chained: + + .large.button + // => "
    " + + The previous defaulted to divs, however you + may also specify the tag type: + + h1.title My Title + // => "

    My Title

    " + +## Id literal + + Much like the class literal there's an id literal: + + #user-1 + // => "
    " + + Again we may specify the tag as well: + + ul#menu + li: a(href='/home') Home + li: a(href='/store') Store + li: a(href='/contact') Contact + + Finally all of these may be used in any combination, + the following are all valid tags: + + a.button#contact(style: 'color: red') Contact + a.button(style: 'color: red')#contact Contact + a(style: 'color: red').button#contact Contact + +## Block expansion + + Jade supports the concept of "block expansion", in which + using a trailing ":" after a tag will inject a block: + + ul + li: a Foo + li: a Bar + li: a Baz + +## Text + + Arbitrary text may follow tags: + + p Welcome to my site + + yields: + +

    Welcome to my site

    + +## Pipe text + + Another form of text is "pipe" text. Pipes act + as the text margin for large bodies of text. + + p + | This is a large + | body of text for + | this tag. + | + | Nothing too + | exciting. + + yields: + +

    This is a large + body of text for + this tag. + + Nothing too + exciting. +

    + + Using pipes we can also specify regular Jade tags + within the text: + + p + | Click to visit + a(href='http://google.com') Google + | if you want. + +## Text only tags + + As an alternative to pipe text you may add + a trailing "." to indicate that the block + contains nothing but plain-text, no tags: + + p. + This is a large + body of text for + this tag. + + Nothing too + exciting. + + Some tags are text-only by default, for example + _script_, _textarea_, and _style_ tags do not + contain nested HTML so Jade implies the trailing ".": + + script + if (foo) { + bar(); + } + + style + body { + padding: 50px; + font: 14px Helvetica; + } + +## Template script tags + + Sometimes it's useful to define HTML in script + tags using Jade, typically for client-side templates. + + To do this simply give the _script_ tag an arbitrary + _type_ attribute such as _text/x-template_: + + script(type='text/template') + h1 Look! + p Jade still works in here! + +## Interpolation + + Both plain-text and piped-text support interpolation, + which comes in two forms, escapes and non-escaped. The + following will output the _user.name_ in the paragraph + but HTML within it will be escaped to prevent XSS attacks: + + p Welcome #{user.name} + + The following syntax is identical however it will _not_ escape + HTML, and should only be used with strings that you trust: + + p Welcome !{user.name} + +## Inline HTML + + Sometimes constructing small inline snippets of HTML + in Jade can be annoying, luckily we can add plain + HTML as well: + + p Welcome #{user.name} + +## Code + + To buffer output with Jade simply use _=_ at the beginning + of a line or after a tag. This method escapes any HTML + present in the string. + + p= user.description + + To buffer output unescaped use the _!=_ variant, but again + be careful of XSS. + + p!= user.description + + The final way to mess with JavaScript code in Jade is the unbuffered + _-_, which can be used for conditionals, defining variables etc: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) { + h2 Description + p.description= user.description + - } + + When compiled blocks are wrapped in anonymous functions, so the + following is also valid, without braces: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) + h2 Description + p.description= user.description + + If you really want you could even use `.forEach()` and others: + + - users.forEach(function(user){ + .user + h2= user.name + p User #{user.name} is #{user.age} years old + - }) + + Taking this further Jade provides some syntax for conditionals, + iteration, switch statements etc. Let's look at those next! + +## Assignment + + Jade's first-class assignment is simple, simply use the _=_ + operator and Jade will _var_ it for you. The following are equivalent: + + - var user = { name: 'tobi' } + user = { name: 'tobi' } + +## Conditionals + + Jade's first-class conditional syntax allows for optional + parenthesis, and you may now omit the leading _-_ otherwise + it's identical, still just regular javascript: + + user = { description: 'foo bar baz' } + #user + if user.description + h2 Description + p.description= user.description + + Jade provides the negated version, _unless_ as well, the following + are equivalent: + + - if (!(user.isAnonymous)) + p You're logged in as #{user.name} + + unless user.isAnonymous + p You're logged in as #{user.name} + +## Iteration + + JavaScript's _for_ loops don't look very declarative, so Jade + also provides its own _for_ loop construct, aliased as _each_: + + for user in users + .user + h2= user.name + p user #{user.name} is #{user.age} year old + + As mentioned _each_ is identical: + + each user in users + .user + h2= user.name + + If necessary the index is available as well: + + for user, i in users + .user(class='user-#{i}') + h2= user.name + + Remember, it's just JavaScript: + + ul#letters + for letter in ['a', 'b', 'c'] + li= letter + +## Mixins + + Mixins provide a way to define jade "functions" which "mix in" + their contents when called. This is useful for abstracting + out large fragments of Jade. + + The simplest possible mixin which accepts no arguments might + look like this: + + mixin hello + p Hello + + You use a mixin by placing `+` before the name: + + +hello + + For something a little more dynamic, mixins can take + arguments, the mixin itself is converted to a javascript + function internally: + + mixin hello(user) + p Hello #{user} + + +hello('Tobi') + + Yields: + +

    Hello Tobi

    + + Mixins may optionally take blocks, when a block is passed + its contents becomes the implicit `block` argument. For + example here is a mixin passed a block, and also invoked + without passing a block: + + mixin article(title) + .article + .article-wrapper + h1= title + if block + block + else + p No content provided + + +article('Hello world') + + +article('Hello world') + p This is my + p Amazing article + + yields: + +
    +
    +

    Hello world

    +

    No content provided

    +
    +
    + +
    +
    +

    Hello world

    +

    This is my

    +

    Amazing article

    +
    +
    + + Mixins can even take attributes, just like a tag. When + attributes are passed they become the implicit `attributes` + argument. Individual attributes can be accessed just like + normal object properties: + + mixin centered + .centered(class=attributes.class) + block + + +centered.bold Hello world + + +centered.red + p This is my + p Amazing article + + yields: + +
    Hello world
    +
    +

    This is my

    +

    Amazing article

    +
    + + If you use `attributes` directly, *all* passed attributes + get used: + + mixin link + a.menu(attributes) + block + + +link.highlight(href='#top') Top + +link#sec1.plain(href='#section1') Section 1 + +link#sec2.plain(href='#section2') Section 2 + + yields: + + Top + Section 1 + Section 2 + + If you pass arguments, they must directly follow the mixin: + + mixin list(arr) + if block + .title + block + ul(attributes) + each item in arr + li= item + + +list(['foo', 'bar', 'baz'])(id='myList', class='bold') + + yields: + +
      +
    • foo
    • +
    • bar
    • +
    • baz
    • +
    diff --git a/node_modules/jade/jade.min.js b/node_modules/jade/jade.min.js new file mode 100644 index 0000000..93f3b3d --- /dev/null +++ b/node_modules/jade/jade.min.js @@ -0,0 +1,2 @@ +(function(){function require(p){var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');return mod.exports||(mod.exports={},mod.call(mod.exports,mod,mod.exports,require.relative(path))),mod.exports}require.modules={},require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig},require.register=function(path,fn){require.modules[path]=fn},require.relative=function(parent){return function(p){if("."!=p.charAt(0))return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i/g,">").replace(/"/g,""")}var nodes=require("./nodes"),filters=require("./filters"),doctypes=require("./doctypes"),selfClosing=require("./self-closing"),runtime=require("./runtime"),utils=require("./utils");Object.keys||(Object.keys=function(obj){var arr=[];for(var key in obj)obj.hasOwnProperty(key)&&arr.push(key);return arr}),String.prototype.trimLeft||(String.prototype.trimLeft=function(){return this.replace(/^\s+/,"")});var Compiler=module.exports=function Compiler(node,options){this.options=options=options||{},this.node=node,this.hasCompiledDoctype=!1,this.hasCompiledTag=!1,this.pp=options.pretty||!1,this.debug=!1!==options.compileDebug,this.indents=0,this.parentIndents=0,options.doctype&&this.setDoctype(options.doctype)};Compiler.prototype={compile:function(){return this.buf=["var interp;"],this.pp&&this.buf.push("var __indent = [];"),this.lastBufferedIdx=-1,this.visit(this.node),this.buf.join("\n")},setDoctype:function(name){name=name&&name.toLowerCase()||"default",this.doctype=doctypes[name]||"",this.terse=this.doctype.toLowerCase()=="",this.xml=0==this.doctype.indexOf("1&&!escape&&block.nodes[0].isText&&block.nodes[1].isText&&this.prettyIndent(1,!0);for(var i=0;i0&&!escape&&block.nodes[i].isText&&block.nodes[i-1].isText&&this.prettyIndent(1,!1),this.visit(block.nodes[i]),block.nodes[i+1]&&block.nodes[i].isText&&block.nodes[i+1].isText&&this.buffer("\\n")},visitDoctype:function(doctype){doctype&&(doctype.val||!this.doctype)&&this.setDoctype(doctype.val||"default"),this.doctype&&this.buffer(this.doctype),this.hasCompiledDoctype=!0},visitMixin:function(mixin){var name=mixin.name.replace(/-/g,"_")+"_mixin",args=mixin.args||"",block=mixin.block,attrs=mixin.attrs,pp=this.pp;if(mixin.call){pp&&this.buf.push("__indent.push('"+Array(this.indents+1).join(" ")+"');");if(block||attrs.length){this.buf.push(name+".call({");if(block){this.buf.push("block: function(){"),this.parentIndents++;var _indents=this.indents;this.indents=0,this.visit(mixin.block),this.indents=_indents,this.parentIndents--,attrs.length?this.buf.push("},"):this.buf.push("}")}if(attrs.length){var val=this.attrs(attrs);val.inherits?this.buf.push("attributes: merge({"+val.buf+"}, attributes), escaped: merge("+val.escaped+", escaped, true)"):this.buf.push("attributes: {"+val.buf+"}, escaped: "+val.escaped)}args?this.buf.push("}, "+args+");"):this.buf.push("});")}else this.buf.push(name+"("+args+");");pp&&this.buf.push("__indent.pop();")}else this.buf.push("var "+name+" = function("+args+"){"),this.buf.push("var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};"),this.parentIndents++,this.visit(block),this.parentIndents--,this.buf.push("};")},visitTag:function(tag){this.indents++;var name=tag.name,pp=this.pp;tag.buffer&&(name="' + ("+name+") + '"),this.hasCompiledTag||(!this.hasCompiledDoctype&&"html"==name&&this.visitDoctype(),this.hasCompiledTag=!0),pp&&!tag.isInline()&&this.prettyIndent(0,!0),(~selfClosing.indexOf(name)||tag.selfClosing)&&!this.xml?(this.buffer("<"+name),this.visitAttributes(tag.attrs),this.terse?this.buffer(">"):this.buffer("/>")):(tag.attrs.length?(this.buffer("<"+name),tag.attrs.length&&this.visitAttributes(tag.attrs),this.buffer(">")):this.buffer("<"+name+">"),tag.code&&this.visitCode(tag.code),this.escape="pre"==tag.name,this.visit(tag.block),pp&&!tag.isInline()&&"pre"!=tag.name&&!tag.canInline()&&this.prettyIndent(0,!0),this.buffer("")),this.indents--},visitFilter:function(filter){var fn=filters[filter.name];if(!fn)throw filter.isASTFilter?new Error('unknown ast filter "'+filter.name+':"'):new Error('unknown filter ":'+filter.name+'"');if(filter.isASTFilter)this.buf.push(fn(filter.block,this,filter.attrs));else{var text=filter.block.nodes.map(function(node){return node.val}).join("\n");filter.attrs=filter.attrs||{},filter.attrs.filename=this.options.filename,this.buffer(utils.text(fn(text,filter.attrs)))}},visitText:function(text){text=utils.text(text.val.replace(/\\/g,"_SLASH_")),this.escape&&(text=escape(text)),text=text.replace(/_SLASH_/g,"\\\\"),this.buffer(text)},visitComment:function(comment){if(!comment.buffer)return;this.pp&&this.prettyIndent(1,!0),this.buffer("")},visitBlockComment:function(comment){if(!comment.buffer)return;0==comment.val.trim().indexOf("if")?(this.buffer("")):(this.buffer(""))},visitCode:function(code){if(code.buffer){var val=code.val.trimLeft();this.buf.push("var __val__ = "+val),val='null == __val__ ? "" : __val__',code.escape&&(val="escape("+val+")"),this.buf.push("buf.push("+val+");")}else this.buf.push(code.val);code.block&&(code.buffer||this.buf.push("{"),this.visit(code.block),code.buffer||this.buf.push("}"))},visitEach:function(each){this.buf.push("// iterate "+each.obj+"\n"+";(function(){\n"+" if ('number' == typeof "+each.obj+".length) {\n"),each.alternative&&this.buf.push(" if ("+each.obj+".length) {"),this.buf.push(" for (var "+each.key+" = 0, $$l = "+each.obj+".length; "+each.key+" < $$l; "+each.key+"++) {\n"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n"),each.alternative&&(this.buf.push(" } else {"),this.visit(each.alternative),this.buf.push(" }")),this.buf.push(" } else {\n var $$l = 0;\n for (var "+each.key+" in "+each.obj+") {\n"+" $$l++;"+" if ("+each.obj+".hasOwnProperty("+each.key+")){"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n"),this.buf.push(" }\n"),each.alternative&&(this.buf.push(" if ($$l === 0) {"),this.visit(each.alternative),this.buf.push(" }")),this.buf.push(" }\n}).call(this);\n")},visitAttributes:function(attrs){var val=this.attrs(attrs);val.inherits?this.buf.push("buf.push(attrs(merge({ "+val.buf+" }, attributes), merge("+val.escaped+", escaped, true)));"):val.constant?(eval("var buf={"+val.buf+"};"),this.buffer(runtime.attrs(buf,JSON.parse(val.escaped)),!0)):this.buf.push("buf.push(attrs({ "+val.buf+" }, "+val.escaped+"));")},attrs:function(attrs){var buf=[],classes=[],escaped={},constant=attrs.every(function(attr){return isConstant(attr.val)}),inherits=!1;return this.terse&&buf.push("terse: true"),attrs.forEach(function(attr){if(attr.name=="attributes")return inherits=!0;escaped[attr.name]=attr.escaped;if(attr.name=="class")classes.push("("+attr.val+")");else{var pair="'"+attr.name+"':("+attr.val+")";buf.push(pair)}}),classes.length&&(classes=classes.join(" + ' ' + "),buf.push("class: "+classes)),{buf:buf.join(", ").replace("class:",'"class":'),escaped:JSON.stringify(escaped),inherits:inherits,constant:constant}}}}),require.register("doctypes.js",function(module,exports,require){module.exports={5:"","default":"",xml:'',transitional:'',strict:'',frameset:'',1.1:'',basic:'',mobile:''}}),require.register("filters.js",function(module,exports,require){module.exports={cdata:function(str){return""},sass:function(str){str=str.replace(/\\n/g,"\n");var sass=require("sass").render(str).replace(/\n/g,"\\n");return'"},stylus:function(str,options){var ret;str=str.replace(/\\n/g,"\n");var stylus=require("stylus");return stylus(str,options).render(function(err,css){if(err)throw err;ret=css.replace(/\n/g,"\\n")}),'"},less:function(str){var ret;return str=str.replace(/\\n/g,"\n"),require("less").render(str,function(err,css){if(err)throw err;ret='"}),ret},markdown:function(str){var md;try{md=require("markdown")}catch(err){try{md=require("discount")}catch(err){try{md=require("markdown-js")}catch(err){try{md=require("marked")}catch(err){throw new Error("Cannot find markdown library, install markdown, discount, or marked.")}}}}return str=str.replace(/\\n/g,"\n"),md.parse(str).replace(/\n/g,"\\n").replace(/'/g,"'")},coffeescript:function(str){var js=require("coffee-script").compile(str).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");return'"}}}),require.register("inline-tags.js",function(module,exports,require){module.exports=["a","abbr","acronym","b","br","code","em","font","i","img","ins","kbd","map","samp","small","span","strong","sub","sup"]}),require.register("jade.js",function(module,exports,require){function parse(str,options){try{var parser=new Parser(str,options.filename,options),compiler=new(options.compiler||Compiler)(parser.parse(),options),js=compiler.compile();return options.debug&&console.error("\nCompiled Function:\n\n%s",js.replace(/^/gm," ")),"var buf = [];\n"+(options.self?"var self = locals || {};\n"+js:"with (locals || {}) {\n"+js+"\n}\n")+'return buf.join("");'}catch(err){parser=parser.context(),runtime.rethrow(err,parser.filename,parser.lexer.lineno)}}function stripBOM(str){return 65279==str.charCodeAt(0)?str.substring(1):str}var Parser=require("./parser"),Lexer=require("./lexer"),Compiler=require("./compiler"),runtime=require("./runtime");exports.version="0.27.6",exports.selfClosing=require("./self-closing"),exports.doctypes=require("./doctypes"),exports.filters=require("./filters"),exports.utils=require("./utils"),exports.Compiler=Compiler,exports.Parser=Parser,exports.Lexer=Lexer,exports.nodes=require("./nodes"),exports.runtime=runtime,exports.cache={},exports.compile=function(str,options){var options=options||{},client=options.client,filename=options.filename?JSON.stringify(options.filename):"undefined",fn;return str=stripBOM(String(str)),options.compileDebug!==!1?fn=["var __jade = [{ lineno: 1, filename: "+filename+" }];","try {",parse(str,options),"} catch (err) {"," rethrow(err, __jade[0].filename, __jade[0].lineno);","}"].join("\n"):fn=parse(str,options),client&&(fn="attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n"+fn),fn=new Function("locals, attrs, escape, rethrow, merge",fn),client?fn:function(locals){return fn(locals,runtime.attrs,runtime.escape,runtime.rethrow,runtime.merge)}},exports.render=function(str,options,fn){"function"==typeof options&&(fn=options,options={});if(options.cache&&!options.filename)return fn(new Error('the "filename" option is required for caching'));try{var path=options.filename,tmpl=options.cache?exports.cache[path]||(exports.cache[path]=exports.compile(str,options)):exports.compile(str,options);fn(null,tmpl(options))}catch(err){fn(err)}},exports.renderFile=function(path,options,fn){var key=path+":string";"function"==typeof options&&(fn=options,options={});try{options.filename=path;var str=options.cache?exports.cache[key]||(exports.cache[key]=fs.readFileSync(path,"utf8")):fs.readFileSync(path,"utf8");exports.render(str,options,fn)}catch(err){fn(err)}},exports.__express=exports.renderFile}),require.register("lexer.js",function(module,exports,require){var utils=require("./utils"),Lexer=module.exports=function Lexer(str,options){options=options||{},this.input=str.replace(/\r\n|\r/g,"\n"),this.colons=options.colons,this.deferredTokens=[],this.lastIndents=0,this.lineno=1,this.stash=[],this.indentStack=[],this.indentRe=null,this.pipeless=!1};Lexer.prototype={tok:function(type,val){return{type:type,line:this.lineno,val:val}},consume:function(len){this.input=this.input.substr(len)},scan:function(regexp,type){var captures;if(captures=regexp.exec(this.input))return this.consume(captures[0].length),this.tok(type,captures[1])},defer:function(tok){this.deferredTokens.push(tok)},lookahead:function(n){var fetch=n-this.stash.length;while(fetch-->0)this.stash.push(this.next());return this.stash[--n]},indexOfDelimiters:function(start,end){var str=this.input,nstart=0,nend=0,pos=0;for(var i=0,len=str.length;iindents)this.stash.push(this.tok("outdent")),this.indentStack.shift();tok=this.stash.pop()}else indents&&indents!=this.indentStack[0]?(this.indentStack.unshift(indents),tok=this.tok("indent",indents)):tok=this.tok("newline");return tok}},pipelessText:function(){if(this.pipeless){if("\n"==this.input[0])return;var i=this.input.indexOf("\n");-1==i&&(i=this.input.length);var str=this.input.substr(0,i);return this.consume(str.length),this.tok("text",str)}},colon:function(){return this.scan(/^: */,":")},advance:function(){return this.stashed()||this.next()},next:function(){return this.deferred()||this.blank()||this.eos()||this.pipelessText()||this.yield()||this.doctype()||this.interpolation()||this["case"]()||this.when()||this["default"]()||this["extends"]()||this.append()||this.prepend()||this.block()||this.include()||this.mixin()||this.call()||this.conditional()||this.each()||this["while"]()||this.assignment()||this.tag()||this.filter()||this.code()||this.id()||this.className()||this.attrs()||this.indent()||this.comment()||this.colon()||this.text()}}}),require.register("nodes/attrs.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Attrs=module.exports=function Attrs(){this.attrs=[]};Attrs.prototype=new Node,Attrs.prototype.constructor=Attrs,Attrs.prototype.setAttribute=function(name,val,escaped){return this.attrs.push({name:name,val:val,escaped:escaped}),this},Attrs.prototype.removeAttribute=function(name){for(var i=0,len=this.attrs.length;i/g,">").replace(/"/g,""")},exports.rethrow=function rethrow(err,filename,lineno){if(!filename)throw err;var context=3,str=require("fs").readFileSync(filename,"utf8"),lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message,err}}),require.register("self-closing.js",function(module,exports,require){module.exports=["meta","img","link","input","source","area","base","col","br","hr"]}),require.register("utils.js",function(module,exports,require){var interpolate=exports.interpolate=function(str){return str.replace(/(_SLASH_)?([#!]){(.*?)}/g,function(str,escape,flag,code){return code=code.replace(/\\'/g,"'").replace(/_SLASH_/g,"\\"),escape?str.slice(7):"' + "+("!"==flag?"":"escape")+"((interp = "+code+") == null ? '' : interp) + '"})},escape=exports.escape=function(str){return str.replace(/'/g,"\\'")};exports.text=function(str){return interpolate(escape(str))},exports.merge=function(a,b){for(var key in b)a[key]=b[key];return a}}),window.jade=require("jade")})(); \ No newline at end of file diff --git a/node_modules/jade/lib/compiler.js b/node_modules/jade/lib/compiler.js new file mode 100644 index 0000000..bb56142 --- /dev/null +++ b/node_modules/jade/lib/compiler.js @@ -0,0 +1,655 @@ + +/*! + * Jade - Compiler + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var nodes = require('./nodes') + , filters = require('./filters') + , doctypes = require('./doctypes') + , selfClosing = require('./self-closing') + , runtime = require('./runtime') + , utils = require('./utils'); + +// if browser +// +// if (!Object.keys) { +// Object.keys = function(obj){ +// var arr = []; +// for (var key in obj) { +// if (obj.hasOwnProperty(key)) { +// arr.push(key); +// } +// } +// return arr; +// } +// } +// +// if (!String.prototype.trimLeft) { +// String.prototype.trimLeft = function(){ +// return this.replace(/^\s+/, ''); +// } +// } +// +// end + + +/** + * Initialize `Compiler` with the given `node`. + * + * @param {Node} node + * @param {Object} options + * @api public + */ + +var Compiler = module.exports = function Compiler(node, options) { + this.options = options = options || {}; + this.node = node; + this.hasCompiledDoctype = false; + this.hasCompiledTag = false; + this.pp = options.pretty || false; + this.debug = false !== options.compileDebug; + this.indents = 0; + this.parentIndents = 0; + if (options.doctype) this.setDoctype(options.doctype); +}; + +/** + * Compiler prototype. + */ + +Compiler.prototype = { + + /** + * Compile parse tree to JavaScript. + * + * @api public + */ + + compile: function(){ + this.buf = ['var interp;']; + if (this.pp) this.buf.push("var __indent = [];"); + this.lastBufferedIdx = -1; + this.visit(this.node); + return this.buf.join('\n'); + }, + + /** + * Sets the default doctype `name`. Sets terse mode to `true` when + * html 5 is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {string} name + * @api public + */ + + setDoctype: function(name){ + name = (name && name.toLowerCase()) || 'default'; + this.doctype = doctypes[name] || ''; + this.terse = this.doctype.toLowerCase() == ''; + this.xml = 0 == this.doctype.indexOf(' 1 && !escape && block.nodes[0].isText && block.nodes[1].isText) + this.prettyIndent(1, true); + + for (var i = 0; i < len; ++i) { + // Pretty print text + if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText) + this.prettyIndent(1, false); + + this.visit(block.nodes[i]); + // Multiple text nodes are separated by newlines + if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText) + this.buffer('\\n'); + } + }, + + /** + * Visit `doctype`. Sets terse mode to `true` when html 5 + * is used, causing self-closing tags to end with ">" vs "/>", + * and boolean attributes are not mirrored. + * + * @param {Doctype} doctype + * @api public + */ + + visitDoctype: function(doctype){ + if (doctype && (doctype.val || !this.doctype)) { + this.setDoctype(doctype.val || 'default'); + } + + if (this.doctype) this.buffer(this.doctype); + this.hasCompiledDoctype = true; + }, + + /** + * Visit `mixin`, generating a function that + * may be called within the template. + * + * @param {Mixin} mixin + * @api public + */ + + visitMixin: function(mixin){ + var name = mixin.name.replace(/-/g, '_') + '_mixin' + , args = mixin.args || '' + , block = mixin.block + , attrs = mixin.attrs + , pp = this.pp; + + if (mixin.call) { + if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');") + if (block || attrs.length) { + + this.buf.push(name + '.call({'); + + if (block) { + this.buf.push('block: function(){'); + + // Render block with no indents, dynamically added when rendered + this.parentIndents++; + var _indents = this.indents; + this.indents = 0; + this.visit(mixin.block); + this.indents = _indents; + this.parentIndents--; + + if (attrs.length) { + this.buf.push('},'); + } else { + this.buf.push('}'); + } + } + + if (attrs.length) { + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push('attributes: merge({' + val.buf + + '}, attributes), escaped: merge(' + val.escaped + ', escaped, true)'); + } else { + this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped); + } + } + + if (args) { + this.buf.push('}, ' + args + ');'); + } else { + this.buf.push('});'); + } + + } else { + this.buf.push(name + '(' + args + ');'); + } + if (pp) this.buf.push("__indent.pop();") + } else { + this.buf.push('var ' + name + ' = function(' + args + '){'); + this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};'); + this.parentIndents++; + this.visit(block); + this.parentIndents--; + this.buf.push('};'); + } + }, + + /** + * Visit `tag` buffering tag markup, generating + * attributes, visiting the `tag`'s code and block. + * + * @param {Tag} tag + * @api public + */ + + visitTag: function(tag){ + this.indents++; + var name = tag.name + , pp = this.pp; + + if (tag.buffer) name = "' + (" + name + ") + '"; + + if (!this.hasCompiledTag) { + if (!this.hasCompiledDoctype && 'html' == name) { + this.visitDoctype(); + } + this.hasCompiledTag = true; + } + + // pretty print + if (pp && !tag.isInline()) + this.prettyIndent(0, true); + + if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) { + this.buffer('<' + name); + this.visitAttributes(tag.attrs); + this.terse + ? this.buffer('>') + : this.buffer('/>'); + } else { + // Optimize attributes buffering + if (tag.attrs.length) { + this.buffer('<' + name); + if (tag.attrs.length) this.visitAttributes(tag.attrs); + this.buffer('>'); + } else { + this.buffer('<' + name + '>'); + } + if (tag.code) this.visitCode(tag.code); + this.escape = 'pre' == tag.name; + this.visit(tag.block); + + // pretty print + if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline()) + this.prettyIndent(0, true); + + this.buffer(''); + } + this.indents--; + }, + + /** + * Visit `filter`, throwing when the filter does not exist. + * + * @param {Filter} filter + * @api public + */ + + visitFilter: function(filter){ + var fn = filters[filter.name]; + + // unknown filter + if (!fn) throw new Error('unknown filter ":' + filter.name + '"'); + + var text = filter.block.nodes.map( + function(node){ return node.val; } + ).join('\n'); + filter.attrs = filter.attrs || {}; + filter.attrs.filename = this.options.filename; + this.buffer(utils.text(fn(text, filter.attrs))); + }, + + /** + * Visit `text` node. + * + * @param {Text} text + * @api public + */ + + visitText: function(text){ + text = utils.text(text.val.replace(/\\/g, '_SLASH_')); + if (this.escape) text = escape(text); + text = text.replace(/_SLASH_/g, '\\\\'); + this.buffer(text); + }, + + /** + * Visit a `comment`, only buffering when the buffer flag is set. + * + * @param {Comment} comment + * @api public + */ + + visitComment: function(comment){ + if (!comment.buffer) return; + if (this.pp) this.prettyIndent(1, true); + this.buffer(''); + }, + + /** + * Visit a `BlockComment`. + * + * @param {Comment} comment + * @api public + */ + + visitBlockComment: function(comment){ + if (!comment.buffer) return; + if (0 == comment.val.trim().indexOf('if')) { + this.buffer(''); + } else { + this.buffer(''); + } + }, + + /** + * Visit `code`, respecting buffer / escape flags. + * If the code is followed by a block, wrap it in + * a self-calling function. + * + * @param {Code} code + * @api public + */ + + visitCode: function(code){ + // Wrap code blocks with {}. + // we only wrap unbuffered code blocks ATM + // since they are usually flow control + + // Buffer code + if (code.buffer) { + var val = code.val.trimLeft(); + this.buf.push('var __val__ = ' + val); + val = 'null == __val__ ? "" : __val__'; + if (code.escape) val = 'escape(' + val + ')'; + this.buf.push("buf.push(" + val + ");"); + } else { + this.buf.push(code.val); + } + + // Block support + if (code.block) { + if (!code.buffer) this.buf.push('{'); + this.visit(code.block); + if (!code.buffer) this.buf.push('}'); + } + }, + + /** + * Visit `each` block. + * + * @param {Each} each + * @api public + */ + + visitEach: function(each){ + this.buf.push('' + + '// iterate ' + each.obj + '\n' + + ';(function(){\n' + + ' if (\'number\' == typeof ' + each.obj + '.length) {\n'); + + if (each.alternative) { + this.buf.push(' if (' + each.obj + '.length) {'); + } + + this.buf.push('' + + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push(' }\n'); + + if (each.alternative) { + this.buf.push(' } else {'); + this.visit(each.alternative); + this.buf.push(' }'); + } + + this.buf.push('' + + ' } else {\n' + + ' var $$l = 0;\n' + + ' for (var ' + each.key + ' in ' + each.obj + ') {\n' + + ' $$l++;' + // if browser + // + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){' + // end + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + // if browser + // this.buf.push(' }\n'); + // end + + this.buf.push(' }\n'); + if (each.alternative) { + this.buf.push(' if ($$l === 0) {'); + this.visit(each.alternative); + this.buf.push(' }'); + } + this.buf.push(' }\n}).call(this);\n'); + }, + + /** + * Visit `attrs`. + * + * @param {Array} attrs + * @api public + */ + + visitAttributes: function(attrs){ + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push("buf.push(attrs(merge({ " + val.buf + + " }, attributes), merge(" + val.escaped + ", escaped, true)));"); + } else if (val.constant) { + eval('var buf={' + val.buf + '};'); + this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true); + } else { + this.buf.push("buf.push(attrs({ " + val.buf + " }, " + val.escaped + "));"); + } + }, + + /** + * Compile attributes. + */ + + attrs: function(attrs){ + var buf = [] + , classes = [] + , escaped = {} + , constant = attrs.every(function(attr){ return isConstant(attr.val) }) + , inherits = false; + + if (this.terse) buf.push('terse: true'); + + attrs.forEach(function(attr){ + if (attr.name == 'attributes') return inherits = true; + escaped[attr.name] = attr.escaped; + if (attr.name == 'class') { + classes.push('(' + attr.val + ')'); + } else { + var pair = "'" + attr.name + "':(" + attr.val + ')'; + buf.push(pair); + } + }); + + if (classes.length) { + classes = classes.join(" + ' ' + "); + buf.push('"class": ' + classes); + } + + return { + buf: buf.join(', '), + escaped: JSON.stringify(escaped), + inherits: inherits, + constant: constant + }; + } +}; + +/** + * Check if expression can be evaluated to a constant + * + * @param {String} expression + * @return {Boolean} + * @api private + */ + +function isConstant(val){ + // Check strings/literals + if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val)) + return true; + + // Check numbers + if (!isNaN(Number(val))) + return true; + + // Check arrays + var matches; + if (matches = /^ *\[(.*)\] *$/.exec(val)) + return matches[1].split(',').every(isConstant); + + return false; +} + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} diff --git a/node_modules/jade/lib/doctypes.js b/node_modules/jade/lib/doctypes.js new file mode 100644 index 0000000..e87ca1e --- /dev/null +++ b/node_modules/jade/lib/doctypes.js @@ -0,0 +1,18 @@ + +/*! + * Jade - doctypes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + '5': '' + , 'default': '' + , 'xml': '' + , 'transitional': '' + , 'strict': '' + , 'frameset': '' + , '1.1': '' + , 'basic': '' + , 'mobile': '' +}; \ No newline at end of file diff --git a/node_modules/jade/lib/filters.js b/node_modules/jade/lib/filters.js new file mode 100644 index 0000000..d633559 --- /dev/null +++ b/node_modules/jade/lib/filters.js @@ -0,0 +1,105 @@ + +/*! + * Jade - filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Wrap text with CDATA block. + */ + +exports.cdata = function(str){ + return ''; +}; + +/** + * Wrap text in script tags. + */ + +exports.js = function(str){ + return ''; +}; + +/** + * Wrap text in style tags. + */ + +exports.css = function(str){ + return ''; +}; + +/** + * Transform stylus to css, wrapped in style tags. + */ + +exports.stylus = function(str, options){ + var ret; + str = str.replace(/\\n/g, '\n'); + var stylus = require('stylus'); + stylus(str, options).render(function(err, css){ + if (err) throw err; + ret = css.replace(/\n/g, '\\n'); + }); + return ''; +}; + +/** + * Transform less to css, wrapped in style tags. + */ + +exports.less = function(str){ + var ret; + str = str.replace(/\\n/g, '\n'); + require('less').render(str, function(err, css){ + if (err) throw err; + ret = ''; + }); + return ret; +}; + +/** + * Transform markdown to html. + */ + +exports.markdown = function(str){ + var md; + + // support markdown / discount + try { + md = require('markdown'); + } catch (err){ + try { + md = require('discount'); + } catch (err) { + try { + md = require('markdown-js'); + } catch (err) { + try { + md = require('marked'); + } catch (err) { + throw new + Error('Cannot find markdown library, install markdown, discount, or marked.'); + } + } + } + } + + str = str.replace(/\\n/g, '\n'); + return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,'''); +}; + +/** + * Transform coffeescript to javascript. + */ + +exports.coffeescript = function(str){ + var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); + return ''; +}; + +// aliases + +exports.md = exports.markdown; +exports.styl = exports.stylus; +exports.coffee = exports.coffeescript; diff --git a/node_modules/jade/lib/inline-tags.js b/node_modules/jade/lib/inline-tags.js new file mode 100644 index 0000000..491de0b --- /dev/null +++ b/node_modules/jade/lib/inline-tags.js @@ -0,0 +1,28 @@ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; \ No newline at end of file diff --git a/node_modules/jade/lib/jade.js b/node_modules/jade/lib/jade.js new file mode 100644 index 0000000..09d61e6 --- /dev/null +++ b/node_modules/jade/lib/jade.js @@ -0,0 +1,253 @@ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Parser = require('./parser') + , Lexer = require('./lexer') + , Compiler = require('./compiler') + , runtime = require('./runtime') +// if node + , fs = require('fs'); +// end + +/** + * Library version. + */ + +exports.version = '0.28.0'; + +/** + * Expose self closing tags. + */ + +exports.selfClosing = require('./self-closing'); + +/** + * Default supported doctypes. + */ + +exports.doctypes = require('./doctypes'); + +/** + * Text filters. + */ + +exports.filters = require('./filters'); + +/** + * Utilities. + */ + +exports.utils = require('./utils'); + +/** + * Expose `Compiler`. + */ + +exports.Compiler = Compiler; + +/** + * Expose `Parser`. + */ + +exports.Parser = Parser; + +/** + * Expose `Lexer`. + */ + +exports.Lexer = Lexer; + +/** + * Nodes. + */ + +exports.nodes = require('./nodes'); + +/** + * Jade runtime helpers. + */ + +exports.runtime = runtime; + +/** + * Template function cache. + */ + +exports.cache = {}; + +/** + * Parse the given `str` of jade and return a function body. + * + * @param {String} str + * @param {Object} options + * @return {String} + * @api private + */ + +function parse(str, options){ + try { + // Parse + var parser = new Parser(str, options.filename, options); + + // Compile + var compiler = new (options.compiler || Compiler)(parser.parse(), options) + , js = compiler.compile(); + + // Debug compiler + if (options.debug) { + console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' ')); + } + + return '' + + 'var buf = [];\n' + + (options.self + ? 'var self = locals || {};\n' + js + : 'with (locals || {}) {\n' + js + '\n}\n') + + 'return buf.join("");'; + } catch (err) { + parser = parser.context(); + runtime.rethrow(err, parser.filename, parser.lexer.lineno); + } +} + +/** + * Strip any UTF-8 BOM off of the start of `str`, if it exists. + * + * @param {String} str + * @return {String} + * @api private + */ + +function stripBOM(str){ + return 0xFEFF == str.charCodeAt(0) + ? str.substring(1) + : str; +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + str = stripBOM(String(str)); + + if (options.compileDebug !== false) { + fn = [ + 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(str, options) + , '} catch (err) {' + , ' rethrow(err, __jade[0].filename, __jade[0].lineno);' + , '}' + ].join('\n'); + } else { + fn = parse(str, options); + } + + if (client) { + fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn; + } + + fn = new Function('locals, attrs, escape, rethrow, merge', fn); + + if (client) return fn; + + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge); + }; +}; + +/** + * Render the given `str` of jade and invoke + * the callback `fn(err, str)`. + * + * Options: + * + * - `cache` enable template caching + * - `filename` filename required for `include` / `extends` and caching + * + * @param {String} str + * @param {Object|Function} options or fn + * @param {Function} fn + * @api public + */ + +exports.render = function(str, options, fn){ + // swap args + if ('function' == typeof options) { + fn = options, options = {}; + } + + // cache requires .filename + if (options.cache && !options.filename) { + return fn(new Error('the "filename" option is required for caching')); + } + + try { + var path = options.filename; + var tmpl = options.cache + ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options)) + : exports.compile(str, options); + fn(null, tmpl(options)); + } catch (err) { + fn(err); + } +}; + +/** + * Render a Jade file at the given `path` and callback `fn(err, str)`. + * + * @param {String} path + * @param {Object|Function} options or callback + * @param {Function} fn + * @api public + */ + +exports.renderFile = function(path, options, fn){ + var key = path + ':string'; + + if ('function' == typeof options) { + fn = options, options = {}; + } + + try { + options.filename = path; + var str = options.cache + ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8')) + : fs.readFileSync(path, 'utf8'); + exports.render(str, options, fn); + } catch (err) { + fn(err); + } +}; + +/** + * Express support. + */ + +exports.__express = exports.renderFile; diff --git a/node_modules/jade/lib/lexer.js b/node_modules/jade/lib/lexer.js new file mode 100644 index 0000000..1e0bfff --- /dev/null +++ b/node_modules/jade/lib/lexer.js @@ -0,0 +1,775 @@ +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +var utils = require('./utils'); + +/** + * Initialize `Lexer` with the given `str`. + * + * Options: + * + * - `colons` allow colons for attr delimiters + * + * @param {String} str + * @param {Object} options + * @api private + */ + +var Lexer = module.exports = function Lexer(str, options) { + options = options || {}; + this.input = str.replace(/\r\n|\r/g, '\n'); + this.colons = options.colons; + this.deferredTokens = []; + this.lastIndents = 0; + this.lineno = 1; + this.stash = []; + this.indentStack = []; + this.indentRe = null; + this.pipeless = false; +}; + +/** + * Lexer prototype. + */ + +Lexer.prototype = { + + /** + * Construct a token with the given `type` and `val`. + * + * @param {String} type + * @param {String} val + * @return {Object} + * @api private + */ + + tok: function(type, val){ + return { + type: type + , line: this.lineno + , val: val + } + }, + + /** + * Consume the given `len` of input. + * + * @param {Number} len + * @api private + */ + + consume: function(len){ + this.input = this.input.substr(len); + }, + + /** + * Scan for `type` with the given `regexp`. + * + * @param {String} type + * @param {RegExp} regexp + * @return {Object} + * @api private + */ + + scan: function(regexp, type){ + var captures; + if (captures = regexp.exec(this.input)) { + this.consume(captures[0].length); + return this.tok(type, captures[1]); + } + }, + + /** + * Defer the given `tok`. + * + * @param {Object} tok + * @api private + */ + + defer: function(tok){ + this.deferredTokens.push(tok); + }, + + /** + * 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.next()); + return this.stash[--n]; + }, + + /** + * Return the indexOf `start` / `end` delimiters. + * + * @param {String} start + * @param {String} end + * @return {Number} + * @api private + */ + + indexOfDelimiters: function(start, end){ + var str = this.input + , nstart = 0 + , nend = 0 + , pos = 0; + for (var i = 0, len = str.length; i < len; ++i) { + if (start == str.charAt(i)) { + ++nstart; + } else if (end == str.charAt(i)) { + if (++nend == nstart) { + pos = i; + break; + } + } + } + return pos; + }, + + /** + * Stashed token. + */ + + stashed: function() { + return this.stash.length + && this.stash.shift(); + }, + + /** + * Deferred token. + */ + + deferred: function() { + return this.deferredTokens.length + && this.deferredTokens.shift(); + }, + + /** + * end-of-source. + */ + + eos: function() { + if (this.input.length) return; + if (this.indentStack.length) { + this.indentStack.shift(); + return this.tok('outdent'); + } else { + return this.tok('eos'); + } + }, + + /** + * Blank line. + */ + + blank: function() { + var captures; + if (captures = /^\n *\n/.exec(this.input)) { + this.consume(captures[0].length - 1); + ++this.lineno; + if (this.pipeless) return this.tok('text', ''); + return this.next(); + } + }, + + /** + * Comment. + */ + + comment: function() { + var captures; + if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('comment', captures[2]); + tok.buffer = '-' != captures[1]; + return tok; + } + }, + + /** + * Interpolated tag. + */ + + interpolation: function() { + var captures; + if (captures = /^#\{(.*?)\}/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('interpolation', captures[1]); + } + }, + + /** + * Tag. + */ + + tag: function() { + var captures; + if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) { + this.consume(captures[0].length); + var tok, name = captures[1]; + if (':' == name[name.length - 1]) { + name = name.slice(0, -1); + tok = this.tok('tag', name); + this.defer(this.tok(':')); + while (' ' == this.input[0]) this.input = this.input.substr(1); + } else { + tok = this.tok('tag', name); + } + tok.selfClosing = !! captures[2]; + return tok; + } + }, + + /** + * Filter. + */ + + filter: function() { + return this.scan(/^:(\w+)/, 'filter'); + }, + + /** + * Doctype. + */ + + doctype: function() { + return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype'); + }, + + /** + * Id. + */ + + id: function() { + return this.scan(/^#([\w-]+)/, 'id'); + }, + + /** + * Class. + */ + + className: function() { + return this.scan(/^\.([\w-]+)/, 'class'); + }, + + /** + * Text. + */ + + text: function() { + return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text'); + }, + + /** + * Extends. + */ + + "extends": function() { + return this.scan(/^extends? +([^\n]+)/, 'extends'); + }, + + /** + * Block prepend. + */ + + prepend: function() { + var captures; + if (captures = /^prepend +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'prepend' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block append. + */ + + append: function() { + var captures; + if (captures = /^append +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = 'append' + , name = captures[1] + , tok = this.tok('block', name); + tok.mode = mode; + return tok; + } + }, + + /** + * Block. + */ + + block: function() { + var captures; + if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var mode = captures[1] || 'replace' + , name = captures[2] + , tok = this.tok('block', name); + + tok.mode = mode; + return tok; + } + }, + + /** + * Yield. + */ + + yield: function() { + return this.scan(/^yield */, 'yield'); + }, + + /** + * Include. + */ + + include: function() { + return this.scan(/^include +([^\n]+)/, 'include'); + }, + + /** + * Case. + */ + + "case": function() { + return this.scan(/^case +([^\n]+)/, 'case'); + }, + + /** + * When. + */ + + when: function() { + return this.scan(/^when +([^:\n]+)/, 'when'); + }, + + /** + * Default. + */ + + "default": function() { + return this.scan(/^default */, 'default'); + }, + + /** + * Assignment. + */ + + assignment: function() { + var captures; + if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) { + this.consume(captures[0].length); + var name = captures[1] + , val = captures[2]; + return this.tok('code', 'var ' + name + ' = (' + val + ');'); + } + }, + + /** + * Call mixin. + */ + + call: function(){ + var captures; + if (captures = /^\+([-\w]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('call', captures[1]); + + // Check for args (not attributes) + if (captures = /^ *\((.*?)\)/.exec(this.input)) { + if (!/^ *[-\w]+ *=/.test(captures[1])) { + this.consume(captures[0].length); + tok.args = captures[1]; + } + } + + return tok; + } + }, + + /** + * Mixin. + */ + + mixin: function(){ + var captures; + if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('mixin', captures[1]); + tok.args = captures[2]; + return tok; + } + }, + + /** + * Conditional. + */ + + conditional: function() { + var captures; + if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) { + this.consume(captures[0].length); + var type = captures[1] + , js = captures[2]; + + switch (type) { + case 'if': js = 'if (' + js + ')'; break; + case 'unless': js = 'if (!(' + js + '))'; break; + case 'else if': js = 'else if (' + js + ')'; break; + case 'else': js = 'else'; break; + } + + return this.tok('code', js); + } + }, + + /** + * While. + */ + + "while": function() { + var captures; + if (captures = /^while +([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('code', 'while (' + captures[1] + ')'); + } + }, + + /** + * Each. + */ + + each: function() { + var captures; + if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var tok = this.tok('each', captures[1]); + tok.key = captures[2] || '$index'; + tok.code = captures[3]; + return tok; + } + }, + + /** + * Code. + */ + + code: function() { + var captures; + if (captures = /^(!?=|-)([^\n]+)/.exec(this.input)) { + this.consume(captures[0].length); + var flags = captures[1]; + captures[1] = captures[2]; + var tok = this.tok('code', captures[1]); + tok.escape = flags.charAt(0) === '='; + tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.indexOfDelimiters('(', ')') + , str = this.input.substr(1, index-1) + , tok = this.tok('attrs') + , len = str.length + , colons = this.colons + , states = ['key'] + , escapedAttr + , key = '' + , val = '' + , quote + , c + , p; + + function state(){ + return states[states.length - 1]; + } + + function interpolate(attr) { + return attr.replace(/(\\)?#\{([^}]+)\}/g, function(_, escape, expr){ + return escape + ? _ + : quote + " + (" + expr + ") + " + quote; + }); + } + + this.consume(index + 1); + tok.attrs = {}; + tok.escaped = {}; + + function parse(c) { + var real = c; + // TODO: remove when people fix ":" + if (colons && ':' == c) c = '='; + switch (c) { + case ',': + case '\n': + switch (state()) { + case 'expr': + case 'array': + case 'string': + case 'object': + val += c; + break; + default: + states.push('key'); + val = val.trim(); + key = key.trim(); + if ('' == key) return; + key = key.replace(/^['"]|['"]$/g, '').replace('!', ''); + tok.escaped[key] = escapedAttr; + tok.attrs[key] = '' == val + ? true + : interpolate(val); + key = val = ''; + } + break; + case '=': + switch (state()) { + case 'key char': + key += real; + break; + case 'val': + case 'expr': + case 'array': + case 'string': + case 'object': + val += real; + break; + default: + escapedAttr = '!' != p; + states.push('val'); + } + break; + case '(': + if ('val' == state() + || 'expr' == state()) states.push('expr'); + val += c; + break; + case ')': + if ('expr' == state() + || 'val' == state()) states.pop(); + val += c; + break; + case '{': + if ('val' == state()) states.push('object'); + val += c; + break; + case '}': + if ('object' == state()) states.pop(); + val += c; + break; + case '[': + if ('val' == state()) states.push('array'); + val += c; + break; + case ']': + if ('array' == state()) states.pop(); + val += c; + break; + case '"': + case "'": + switch (state()) { + case 'key': + states.push('key char'); + break; + case 'key char': + states.pop(); + break; + case 'string': + if (c == quote) states.pop(); + val += c; + break; + default: + states.push('string'); + val += c; + quote = c; + } + break; + case '': + break; + default: + switch (state()) { + case 'key': + case 'key char': + key += c; + break; + default: + val += c; + } + } + p = c; + } + + for (var i = 0; i < len; ++i) { + parse(str.charAt(i)); + } + + parse(','); + + if ('/' == this.input.charAt(0)) { + this.consume(1); + tok.selfClosing = true; + } + + return tok; + } + }, + + /** + * Indent | Outdent | Newline. + */ + + indent: function() { + var captures, re; + + // established regexp + if (this.indentRe) { + captures = this.indentRe.exec(this.input); + // determine regexp + } else { + // tabs + re = /^\n(\t*) */; + captures = re.exec(this.input); + + // spaces + if (captures && !captures[1].length) { + re = /^\n( *)/; + captures = re.exec(this.input); + } + + // established + if (captures && captures[1].length) this.indentRe = re; + } + + if (captures) { + var tok + , indents = captures[1].length; + + ++this.lineno; + this.consume(indents + 1); + + if (' ' == this.input[0] || '\t' == this.input[0]) { + throw new Error('Invalid indentation, you can use tabs or spaces but not both'); + } + + // blank line + if ('\n' == this.input[0]) return this.tok('newline'); + + // outdent + if (this.indentStack.length && indents < this.indentStack[0]) { + while (this.indentStack.length && this.indentStack[0] > indents) { + this.stash.push(this.tok('outdent')); + this.indentStack.shift(); + } + tok = this.stash.pop(); + // indent + } else if (indents && indents != this.indentStack[0]) { + this.indentStack.unshift(indents); + tok = this.tok('indent', indents); + // newline + } else { + tok = this.tok('newline'); + } + + return tok; + } + }, + + /** + * Pipe-less text consumed only when + * pipeless is true; + */ + + pipelessText: function() { + if (this.pipeless) { + if ('\n' == this.input[0]) return; + var i = this.input.indexOf('\n'); + if (-1 == i) i = this.input.length; + var str = this.input.substr(0, i); + this.consume(str.length); + return this.tok('text', str); + } + }, + + /** + * ':' + */ + + colon: function() { + return this.scan(/^: */, ':'); + }, + + /** + * Return the next token object, or those + * previously stashed by lookahead. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.stashed() + || this.next(); + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + next: function() { + return this.deferred() + || this.blank() + || this.eos() + || this.pipelessText() + || this.yield() + || this.doctype() + || this.interpolation() + || this["case"]() + || this.when() + || this["default"]() + || this["extends"]() + || this.append() + || this.prepend() + || this.block() + || this.include() + || this.mixin() + || this.call() + || this.conditional() + || this.each() + || this["while"]() + || this.assignment() + || this.tag() + || this.filter() + || this.code() + || this.id() + || this.className() + || this.attrs() + || this.indent() + || this.comment() + || this.colon() + || this.text(); + } +}; diff --git a/node_modules/jade/lib/nodes/attrs.js b/node_modules/jade/lib/nodes/attrs.js new file mode 100644 index 0000000..5de9b59 --- /dev/null +++ b/node_modules/jade/lib/nodes/attrs.js @@ -0,0 +1,77 @@ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'), + Block = require('./block'); + +/** + * Initialize a `Attrs` node. + * + * @api public + */ + +var Attrs = module.exports = function Attrs() { + this.attrs = []; +}; + +/** + * Inherit from `Node`. + */ + +Attrs.prototype.__proto__ = Node.prototype; + +/** + * Set attribute `name` to `val`, keep in mind these become + * part of a raw js object literal, so to quote a value you must + * '"quote me"', otherwise or example 'user.name' is literal JavaScript. + * + * @param {String} name + * @param {String} val + * @param {Boolean} escaped + * @return {Tag} for chaining + * @api public + */ + +Attrs.prototype.setAttribute = function(name, val, escaped){ + this.attrs.push({ name: name, val: val, escaped: escaped }); + return this; +}; + +/** + * Remove attribute `name` when present. + * + * @param {String} name + * @api public + */ + +Attrs.prototype.removeAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + delete this.attrs[i]; + } + } +}; + +/** + * Get attribute value by `name`. + * + * @param {String} name + * @return {String} + * @api public + */ + +Attrs.prototype.getAttribute = function(name){ + for (var i = 0, len = this.attrs.length; i < len; ++i) { + if (this.attrs[i] && this.attrs[i].name == name) { + return this.attrs[i].val; + } + } +}; diff --git a/node_modules/jade/lib/nodes/block-comment.js b/node_modules/jade/lib/nodes/block-comment.js new file mode 100644 index 0000000..4f41e4a --- /dev/null +++ b/node_modules/jade/lib/nodes/block-comment.js @@ -0,0 +1,33 @@ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `BlockComment` with the given `block`. + * + * @param {String} val + * @param {Block} block + * @param {Boolean} buffer + * @api public + */ + +var BlockComment = module.exports = function BlockComment(val, block, buffer) { + this.block = block; + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +BlockComment.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/block.js b/node_modules/jade/lib/nodes/block.js new file mode 100644 index 0000000..6bb18c9 --- /dev/null +++ b/node_modules/jade/lib/nodes/block.js @@ -0,0 +1,122 @@ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Block` with an optional `node`. + * + * @param {Node} node + * @api public + */ + +var Block = module.exports = function Block(node){ + this.nodes = []; + if (node) this.push(node); +}; + +/** + * Inherit from `Node`. + */ + +Block.prototype.__proto__ = Node.prototype; + +/** + * Block flag. + */ + +Block.prototype.isBlock = true; + +/** + * Replace the nodes in `other` with the nodes + * in `this` block. + * + * @param {Block} other + * @api private + */ + +Block.prototype.replace = function(other){ + other.nodes = this.nodes; +}; + +/** + * Pust the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.push = function(node){ + return this.nodes.push(node); +}; + +/** + * Check if this block is empty. + * + * @return {Boolean} + * @api public + */ + +Block.prototype.isEmpty = function(){ + return 0 == this.nodes.length; +}; + +/** + * Unshift the given `node`. + * + * @param {Node} node + * @return {Number} + * @api public + */ + +Block.prototype.unshift = function(node){ + return this.nodes.unshift(node); +}; + +/** + * Return the "last" block, or the first `yield` node. + * + * @return {Block} + * @api private + */ + +Block.prototype.includeBlock = function(){ + var ret = this + , node; + + for (var i = 0, len = this.nodes.length; i < len; ++i) { + node = this.nodes[i]; + if (node.yield) return node; + else if (node.textOnly) continue; + else if (node.includeBlock) ret = node.includeBlock(); + else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock(); + if (ret.yield) return ret; + } + + return ret; +}; + +/** + * Return a clone of this block. + * + * @return {Block} + * @api private + */ + +Block.prototype.clone = function(){ + var clone = new Block; + for (var i = 0, len = this.nodes.length; i < len; ++i) { + clone.push(this.nodes[i].clone()); + } + return clone; +}; + diff --git a/node_modules/jade/lib/nodes/case.js b/node_modules/jade/lib/nodes/case.js new file mode 100644 index 0000000..08ff033 --- /dev/null +++ b/node_modules/jade/lib/nodes/case.js @@ -0,0 +1,43 @@ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a new `Case` with `expr`. + * + * @param {String} expr + * @api public + */ + +var Case = exports = module.exports = function Case(expr, block){ + this.expr = expr; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Case.prototype.__proto__ = Node.prototype; + +var When = exports.When = function When(expr, block){ + this.expr = expr; + this.block = block; + this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +When.prototype.__proto__ = Node.prototype; + diff --git a/node_modules/jade/lib/nodes/code.js b/node_modules/jade/lib/nodes/code.js new file mode 100644 index 0000000..babc675 --- /dev/null +++ b/node_modules/jade/lib/nodes/code.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Code` node with the given code `val`. + * Code may also be optionally buffered and escaped. + * + * @param {String} val + * @param {Boolean} buffer + * @param {Boolean} escape + * @api public + */ + +var Code = module.exports = function Code(val, buffer, escape) { + this.val = val; + this.buffer = buffer; + this.escape = escape; + if (val.match(/^ *else/)) this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +Code.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/comment.js b/node_modules/jade/lib/nodes/comment.js new file mode 100644 index 0000000..2e1469e --- /dev/null +++ b/node_modules/jade/lib/nodes/comment.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Comment` with the given `val`, optionally `buffer`, + * otherwise the comment may render in the output. + * + * @param {String} val + * @param {Boolean} buffer + * @api public + */ + +var Comment = module.exports = function Comment(val, buffer) { + this.val = val; + this.buffer = buffer; +}; + +/** + * Inherit from `Node`. + */ + +Comment.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/doctype.js b/node_modules/jade/lib/nodes/doctype.js new file mode 100644 index 0000000..b8f33e5 --- /dev/null +++ b/node_modules/jade/lib/nodes/doctype.js @@ -0,0 +1,29 @@ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Doctype` with the given `val`. + * + * @param {String} val + * @api public + */ + +var Doctype = module.exports = function Doctype(val) { + this.val = val; +}; + +/** + * Inherit from `Node`. + */ + +Doctype.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/each.js b/node_modules/jade/lib/nodes/each.js new file mode 100644 index 0000000..f54101f --- /dev/null +++ b/node_modules/jade/lib/nodes/each.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize an `Each` node, representing iteration + * + * @param {String} obj + * @param {String} val + * @param {String} key + * @param {Block} block + * @api public + */ + +var Each = module.exports = function Each(obj, val, key, block) { + this.obj = obj; + this.val = val; + this.key = key; + this.block = block; +}; + +/** + * Inherit from `Node`. + */ + +Each.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/filter.js b/node_modules/jade/lib/nodes/filter.js new file mode 100644 index 0000000..0d7ff6e --- /dev/null +++ b/node_modules/jade/lib/nodes/filter.js @@ -0,0 +1,34 @@ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node') + , Block = require('./block'); + +/** + * Initialize a `Filter` node with the given + * filter `name` and `block`. + * + * @param {String} name + * @param {Block|Node} block + * @api public + */ + +var Filter = module.exports = function Filter(name, block, attrs) { + this.name = name; + this.block = block; + this.attrs = attrs; +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/index.js b/node_modules/jade/lib/nodes/index.js new file mode 100644 index 0000000..386ad2f --- /dev/null +++ b/node_modules/jade/lib/nodes/index.js @@ -0,0 +1,20 @@ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +exports.Node = require('./node'); +exports.Tag = require('./tag'); +exports.Code = require('./code'); +exports.Each = require('./each'); +exports.Case = require('./case'); +exports.Text = require('./text'); +exports.Block = require('./block'); +exports.Mixin = require('./mixin'); +exports.Filter = require('./filter'); +exports.Comment = require('./comment'); +exports.Literal = require('./literal'); +exports.BlockComment = require('./block-comment'); +exports.Doctype = require('./doctype'); diff --git a/node_modules/jade/lib/nodes/literal.js b/node_modules/jade/lib/nodes/literal.js new file mode 100644 index 0000000..fde586b --- /dev/null +++ b/node_modules/jade/lib/nodes/literal.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Literal` node with the given `str. + * + * @param {String} str + * @api public + */ + +var Literal = module.exports = function Literal(str) { + this.str = str + .replace(/\\/g, "\\\\") + .replace(/\n|\r\n/g, "\\n") + .replace(/'/g, "\\'"); +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype.__proto__ = Node.prototype; diff --git a/node_modules/jade/lib/nodes/mixin.js b/node_modules/jade/lib/nodes/mixin.js new file mode 100644 index 0000000..8407bc7 --- /dev/null +++ b/node_modules/jade/lib/nodes/mixin.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'); + +/** + * Initialize a new `Mixin` with `name` and `block`. + * + * @param {String} name + * @param {String} args + * @param {Block} block + * @api public + */ + +var Mixin = module.exports = function Mixin(name, args, block, call){ + this.name = name; + this.args = args; + this.block = block; + this.attrs = []; + this.call = call; +}; + +/** + * Inherit from `Attrs`. + */ + +Mixin.prototype.__proto__ = Attrs.prototype; + diff --git a/node_modules/jade/lib/nodes/node.js b/node_modules/jade/lib/nodes/node.js new file mode 100644 index 0000000..e98f042 --- /dev/null +++ b/node_modules/jade/lib/nodes/node.js @@ -0,0 +1,25 @@ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Initialize a `Node`. + * + * @api public + */ + +var Node = module.exports = function Node(){}; + +/** + * Clone this node (return itself) + * + * @return {Node} + * @api private + */ + +Node.prototype.clone = function(){ + return this; +}; diff --git a/node_modules/jade/lib/nodes/tag.js b/node_modules/jade/lib/nodes/tag.js new file mode 100644 index 0000000..4b6728a --- /dev/null +++ b/node_modules/jade/lib/nodes/tag.js @@ -0,0 +1,95 @@ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Attrs = require('./attrs'), + Block = require('./block'), + inlineTags = require('../inline-tags'); + +/** + * Initialize a `Tag` node with the given tag `name` and optional `block`. + * + * @param {String} name + * @param {Block} block + * @api public + */ + +var Tag = module.exports = function Tag(name, block) { + this.name = name; + this.attrs = []; + this.block = block || new Block; +}; + +/** + * Inherit from `Attrs`. + */ + +Tag.prototype.__proto__ = Attrs.prototype; + +/** + * Clone this tag. + * + * @return {Tag} + * @api private + */ + +Tag.prototype.clone = function(){ + var clone = new Tag(this.name, this.block.clone()); + clone.line = this.line; + clone.attrs = this.attrs; + clone.textOnly = this.textOnly; + return clone; +}; + +/** + * Check if this tag is an inline tag. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.isInline = function(){ + return ~inlineTags.indexOf(this.name); +}; + +/** + * Check if this tag's contents can be inlined. Used for pretty printing. + * + * @return {Boolean} + * @api private + */ + +Tag.prototype.canInline = function(){ + var nodes = this.block.nodes; + + function isInline(node){ + // Recurse if the node is a block + if (node.isBlock) return node.nodes.every(isInline); + return node.isText || (node.isInline && node.isInline()); + } + + // Empty tag + if (!nodes.length) return true; + + // Text-only or inline-only tag + if (1 == nodes.length) return isInline(nodes[0]); + + // Multi-line inline-only tag + if (this.block.nodes.every(isInline)) { + for (var i = 1, len = nodes.length; i < len; ++i) { + if (nodes[i-1].isText && nodes[i].isText) + return false; + } + return true; + } + + // Mixed tag + return false; +}; \ No newline at end of file diff --git a/node_modules/jade/lib/nodes/text.js b/node_modules/jade/lib/nodes/text.js new file mode 100644 index 0000000..3b5dd55 --- /dev/null +++ b/node_modules/jade/lib/nodes/text.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Node = require('./node'); + +/** + * Initialize a `Text` node with optional `line`. + * + * @param {String} line + * @api public + */ + +var Text = module.exports = function Text(line) { + this.val = ''; + if ('string' == typeof line) this.val = line; +}; + +/** + * Inherit from `Node`. + */ + +Text.prototype.__proto__ = Node.prototype; + +/** + * Flag as text. + */ + +Text.prototype.isText = true; \ No newline at end of file diff --git a/node_modules/jade/lib/parser.js b/node_modules/jade/lib/parser.js new file mode 100644 index 0000000..5039c90 --- /dev/null +++ b/node_modules/jade/lib/parser.js @@ -0,0 +1,699 @@ + +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes') + , utils = require('./utils') + , filters = require('./filters') + , path = require('path') + , extname = path.extname; + +/** + * Initialize `Parser` with the given input `str` and `filename`. + * + * @param {String} str + * @param {String} filename + * @param {Object} options + * @api public + */ + +var Parser = exports = module.exports = function Parser(str, filename, options){ + this.input = str; + this.lexer = new Lexer(str, options); + this.filename = filename; + this.blocks = {}; + this.mixins = {}; + this.options = options; + this.contexts = [this]; +}; + +/** + * Tags that may not contain tags. + */ + +var textOnly = exports.textOnly = ['script', 'style']; + +/** + * Parser prototype. + */ + +Parser.prototype = { + + /** + * Push `parser` onto the context stack, + * or pop and return a `Parser`. + */ + + context: function(parser){ + if (parser) { + this.contexts.push(parser); + } else { + return this.contexts.pop(); + } + }, + + /** + * Return the next token object. + * + * @return {Object} + * @api private + */ + + advance: function(){ + return this.lexer.advance(); + }, + + /** + * Skip `n` tokens. + * + * @param {Number} n + * @api private + */ + + skip: function(n){ + while (n--) this.advance(); + }, + + /** + * Single token lookahead. + * + * @return {Object} + * @api private + */ + + peek: function() { + return this.lookahead(1); + }, + + /** + * Return lexer lineno. + * + * @return {Number} + * @api private + */ + + line: function() { + return this.lexer.lineno; + }, + + /** + * `n` token lookahead. + * + * @param {Number} n + * @return {Object} + * @api private + */ + + lookahead: function(n){ + return this.lexer.lookahead(n); + }, + + /** + * Parse input returning a string of js for evaluation. + * + * @return {String} + * @api public + */ + + parse: function(){ + var block = new nodes.Block, parser; + block.line = this.line(); + + while ('eos' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + + if (parser = this.extending) { + this.context(parser); + var ast = parser.parse(); + this.context(); + // hoist mixins + for (var name in this.mixins) + ast.unshift(this.mixins[name]); + return ast; + } + + return block; + }, + + /** + * Expect the given type, or throw an exception. + * + * @param {String} type + * @api private + */ + + expect: function(type){ + if (this.peek().type === type) { + return this.advance(); + } else { + throw new Error('expected "' + type + '", but got "' + this.peek().type + '"'); + } + }, + + /** + * Accept the given `type`. + * + * @param {String} type + * @api private + */ + + accept: function(type){ + if (this.peek().type === type) { + return this.advance(); + } + }, + + /** + * tag + * | doctype + * | mixin + * | include + * | filter + * | comment + * | text + * | each + * | code + * | yield + * | id + * | class + * | interpolation + */ + + parseExpr: function(){ + switch (this.peek().type) { + case 'tag': + return this.parseTag(); + case 'mixin': + return this.parseMixin(); + case 'block': + return this.parseBlock(); + case 'case': + return this.parseCase(); + case 'when': + return this.parseWhen(); + case 'default': + return this.parseDefault(); + case 'extends': + return this.parseExtends(); + case 'include': + return this.parseInclude(); + case 'doctype': + return this.parseDoctype(); + case 'filter': + return this.parseFilter(); + case 'comment': + return this.parseComment(); + case 'text': + return this.parseText(); + case 'each': + return this.parseEach(); + case 'code': + return this.parseCode(); + case 'call': + return this.parseCall(); + case 'interpolation': + return this.parseInterpolation(); + case 'yield': + this.advance(); + var block = new nodes.Block; + block.yield = true; + return block; + case 'id': + case 'class': + var tok = this.advance(); + this.lexer.defer(this.lexer.tok('tag', 'div')); + this.lexer.defer(tok); + return this.parseExpr(); + default: + throw new Error('unexpected token "' + this.peek().type + '"'); + } + }, + + /** + * Text + */ + + parseText: function(){ + var tok = this.expect('text'); + var node = new nodes.Text(tok.val); + node.line = this.line(); + return node; + }, + + /** + * ':' expr + * | block + */ + + parseBlockExpansion: function(){ + if (':' == this.peek().type) { + this.advance(); + return new nodes.Block(this.parseExpr()); + } else { + return this.block(); + } + }, + + /** + * case + */ + + parseCase: function(){ + var val = this.expect('case').val; + var node = new nodes.Case(val); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * when + */ + + parseWhen: function(){ + var val = this.expect('when').val + return new nodes.Case.When(val, this.parseBlockExpansion()); + }, + + /** + * default + */ + + parseDefault: function(){ + this.expect('default'); + return new nodes.Case.When('default', this.parseBlockExpansion()); + }, + + /** + * code + */ + + parseCode: function(){ + var tok = this.expect('code'); + var node = new nodes.Code(tok.val, tok.buffer, tok.escape); + var block; + var i = 1; + node.line = this.line(); + while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i; + block = 'indent' == this.lookahead(i).type; + if (block) { + this.skip(i-1); + node.block = this.block(); + } + return node; + }, + + /** + * comment + */ + + parseComment: function(){ + var tok = this.expect('comment'); + var node; + + if ('indent' == this.peek().type) { + node = new nodes.BlockComment(tok.val, this.block(), tok.buffer); + } else { + node = new nodes.Comment(tok.val, tok.buffer); + } + + node.line = this.line(); + return node; + }, + + /** + * doctype + */ + + parseDoctype: function(){ + var tok = this.expect('doctype'); + var node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var tok = this.expect('filter'); + var attrs = this.accept('attrs'); + var block; + + this.lexer.pipeless = true; + block = this.parseTextBlock(); + this.lexer.pipeless = false; + + var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs); + node.line = this.line(); + return node; + }, + + /** + * each block + */ + + parseEach: function(){ + var tok = this.expect('each'); + var node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + if (this.peek().type == 'code' && this.peek().val == 'else') { + this.advance(); + node.alternative = this.block(); + } + return node; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var path = require('path'); + var fs = require('fs'); + var dirname = path.dirname; + var basename = path.basename; + var join = path.join; + + if (!this.filename) + throw new Error('the "filename" option is required to extend templates'); + + var path = this.expect('extends').val.trim(); + var dir = dirname(this.filename); + + var path = join(dir, path + '.jade'); + var str = fs.readFileSync(path, 'utf8'); + var parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block'); + var mode = block.mode; + var name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name]; + + if (prev) { + switch (prev.mode) { + case 'append': + block.nodes = block.nodes.concat(prev.nodes); + prev = block; + break; + case 'prepend': + block.nodes = prev.nodes.concat(block.nodes); + prev = block; + break; + } + } + + block.mode = mode; + return this.blocks[name] = prev || block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var path = require('path'); + var fs = require('fs'); + var dirname = path.dirname; + var basename = path.basename; + var join = path.join; + + var path = this.expect('include').val.trim(); + var dir = dirname(this.filename); + + if (!this.filename) + throw new Error('the "filename" option is required to use includes'); + + // no extension + if (!~basename(path).indexOf('.')) { + path += '.jade'; + } + + // non-jade + if ('.jade' != path.substr(-5)) { + var path = join(dir, path); + var str = fs.readFileSync(path, 'utf8'); + var ext = extname(path).slice(1); + var filter = filters[ext]; + if (filter) str = filter(str, { filename: path }).replace(/\\n/g, '\n'); + return new nodes.Literal(str); + } + + var path = join(dir, path); + var str = fs.readFileSync(path, 'utf8'); + var parser = new Parser(str, path, this.options); + parser.blocks = utils.merge({}, this.blocks); + parser.mixins = this.mixins; + + this.context(parser); + var ast = parser.parse(); + this.context(); + ast.filename = path; + + if ('indent' == this.peek().type) { + ast.includeBlock().push(this.block()); + } + + return ast; + }, + + /** + * call ident block + */ + + parseCall: function(){ + var tok = this.expect('call'); + var name = tok.val; + var args = tok.args; + var mixin = new nodes.Mixin(name, args, new nodes.Block, true); + + this.tag(mixin); + if (mixin.block.isEmpty()) mixin.block = null; + return mixin; + }, + + /** + * mixin block + */ + + parseMixin: function(){ + var tok = this.expect('mixin'); + var name = tok.val; + var args = tok.args; + var mixin; + + // definition + if ('indent' == this.peek().type) { + mixin = new nodes.Mixin(name, args, this.block(), false); + this.mixins[name] = mixin; + return mixin; + // call + } else { + return new nodes.Mixin(name, args, null, true); + } + }, + + /** + * indent (text | newline)* outdent + */ + + parseTextBlock: function(){ + var block = new nodes.Block; + block.line = this.line(); + var spaces = this.expect('indent').val; + if (null == this._spaces) this._spaces = spaces; + var indent = Array(spaces - this._spaces + 1).join(' '); + while ('outdent' != this.peek().type) { + switch (this.peek().type) { + case 'newline': + this.advance(); + break; + case 'indent': + this.parseTextBlock().nodes.forEach(function(node){ + block.push(node); + }); + break; + default: + var text = new nodes.Text(indent + this.advance().val); + text.line = this.line(); + block.push(text); + } + } + + if (spaces == this._spaces) this._spaces = null; + this.expect('outdent'); + return block; + }, + + /** + * indent expr* outdent + */ + + block: function(){ + var block = new nodes.Block; + block.line = this.line(); + this.expect('indent'); + while ('outdent' != this.peek().type) { + if ('newline' == this.peek().type) { + this.advance(); + } else { + block.push(this.parseExpr()); + } + } + this.expect('outdent'); + return block; + }, + + /** + * interpolation (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseInterpolation: function(){ + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + tag.buffer = true; + return this.tag(tag); + }, + + /** + * tag (attrs | class | id)* (text | code | ':')? newline* block? + */ + + parseTag: function(){ + // ast-filter look-ahead + var i = 2; + if ('attrs' == this.lookahead(i).type) ++i; + + var tok = this.advance(); + var tag = new nodes.Tag(tok.val); + + tag.selfClosing = tok.selfClosing; + + return this.tag(tag); + }, + + /** + * Parse tag. + */ + + tag: function(tag){ + var dot; + + tag.line = this.line(); + + // (attrs | class | id)* + out: + while (true) { + switch (this.peek().type) { + case 'id': + case 'class': + var tok = this.advance(); + tag.setAttribute(tok.type, "'" + tok.val + "'"); + continue; + case 'attrs': + var tok = this.advance() + , obj = tok.attrs + , escaped = tok.escaped + , names = Object.keys(obj); + + if (tok.selfClosing) tag.selfClosing = true; + + for (var i = 0, len = names.length; i < len; ++i) { + var name = names[i] + , val = obj[name]; + tag.setAttribute(name, val, escaped[name]); + } + continue; + default: + break out; + } + } + + // check immediate '.' + if ('.' == this.peek().val) { + dot = tag.textOnly = true; + this.advance(); + } + + // (text | code | ':')? + switch (this.peek().type) { + case 'text': + tag.block.push(this.parseText()); + break; + case 'code': + tag.code = this.parseCode(); + break; + case ':': + this.advance(); + tag.block = new nodes.Block; + tag.block.push(this.parseExpr()); + break; + } + + // newline* + while ('newline' == this.peek().type) this.advance(); + + tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name); + + // script special-case + if ('script' == tag.name) { + var type = tag.getAttribute('type'); + if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) { + tag.textOnly = false; + } + } + + // block? + if ('indent' == this.peek().type) { + if (tag.textOnly) { + this.lexer.pipeless = true; + tag.block = this.parseTextBlock(); + this.lexer.pipeless = false; + } else { + var block = this.block(); + if (tag.block) { + for (var i = 0, len = block.nodes.length; i < len; ++i) { + tag.block.push(block.nodes[i]); + } + } else { + tag.block = block; + } + } + } + + return tag; + } +}; diff --git a/node_modules/jade/lib/runtime.js b/node_modules/jade/lib/runtime.js new file mode 100644 index 0000000..fb711f5 --- /dev/null +++ b/node_modules/jade/lib/runtime.js @@ -0,0 +1,174 @@ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + ac = ac.filter(nulls); + bc = bc.filter(nulls); + a['class'] = ac.concat(bc).join(' '); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function nulls(val) { + return val != null; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!(\w+|\#\d+);)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno){ + if (!filename) throw err; + + var context = 3 + , str = require('fs').readFileSync(filename, 'utf8') + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; diff --git a/node_modules/jade/lib/self-closing.js b/node_modules/jade/lib/self-closing.js new file mode 100644 index 0000000..0548771 --- /dev/null +++ b/node_modules/jade/lib/self-closing.js @@ -0,0 +1,19 @@ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; \ No newline at end of file diff --git a/node_modules/jade/lib/utils.js b/node_modules/jade/lib/utils.js new file mode 100644 index 0000000..ca4a7fa --- /dev/null +++ b/node_modules/jade/lib/utils.js @@ -0,0 +1,68 @@ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Convert interpolation in the given string to JavaScript. + * + * @param {String} str + * @return {String} + * @api private + */ + +var interpolate = exports.interpolate = function(str){ + return str.replace(/(_SLASH_)?([#!]){(.*?)}/g, function(str, escape, flag, code){ + code = code + .replace(/\\'/g, "'") + .replace(/_SLASH_/g, '\\'); + + return escape + ? str.slice(7) + : "' + " + + ('!' == flag ? '' : 'escape') + + "((interp = " + code + + ") == null ? '' : interp) + '"; + }); +}; + +/** + * Escape single quotes in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +var escape = exports.escape = function(str) { + return str.replace(/'/g, "\\'"); +}; + +/** + * Interpolate, and escape the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.text = function(str){ + return interpolate(escape(str)); +}; + +/** + * Merge `b` into `a`. + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api public + */ + +exports.merge = function(a, b) { + for (var key in b) a[key] = b[key]; + return a; +}; + diff --git a/node_modules/jade/node_modules/.bin/cake b/node_modules/jade/node_modules/.bin/cake new file mode 100755 index 0000000..5965f4e --- /dev/null +++ b/node_modules/jade/node_modules/.bin/cake @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/cake').run(); diff --git a/node_modules/jade/node_modules/.bin/coffee b/node_modules/jade/node_modules/.bin/coffee new file mode 100755 index 0000000..3d1d71c --- /dev/null +++ b/node_modules/jade/node_modules/.bin/coffee @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/command').run(); diff --git a/node_modules/jade/node_modules/coffee-script/.npmignore b/node_modules/jade/node_modules/coffee-script/.npmignore new file mode 100644 index 0000000..21e430d --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/.npmignore @@ -0,0 +1,11 @@ +*.coffee +*.html +.DS_Store +.git* +Cakefile +documentation/ +examples/ +extras/coffee-script.js +raw/ +src/ +test/ diff --git a/node_modules/jade/node_modules/coffee-script/CNAME b/node_modules/jade/node_modules/coffee-script/CNAME new file mode 100644 index 0000000..faadabe --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/CNAME @@ -0,0 +1 @@ +coffeescript.org \ No newline at end of file diff --git a/node_modules/jade/node_modules/coffee-script/CONTRIBUTING.md b/node_modules/jade/node_modules/coffee-script/CONTRIBUTING.md new file mode 100644 index 0000000..6390c68 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/CONTRIBUTING.md @@ -0,0 +1,9 @@ +## How to contribute to CoffeeScript + +* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/coffee-script/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. + +* Before sending a pull request for a feature, be sure to have [tests](https://github.com/jashkenas/coffee-script/tree/master/test). + +* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffee-script/tree/master/src). If you're just getting started with CoffeeScript, there's a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide). + +* In your pull request, do not add documentation to `index.html` or re-build the minified `coffee-script.js` file. We'll do those things before cutting a new release. \ No newline at end of file diff --git a/node_modules/jade/node_modules/coffee-script/LICENSE b/node_modules/jade/node_modules/coffee-script/LICENSE new file mode 100644 index 0000000..dbe6b4e --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2012 Jeremy Ashkenas + +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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/coffee-script/README b/node_modules/jade/node_modules/coffee-script/README new file mode 100644 index 0000000..69ee6f4 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/README @@ -0,0 +1,51 @@ + + { + } } { + { { } } + } }{ { + { }{ } } _____ __ __ + ( }{ }{ { ) / ____| / _|/ _| + .- { { } { }} -. | | ___ | |_| |_ ___ ___ + ( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \ + |`-..________ ..-'| | |___| (_) | | | || __/ __/ + | | \_____\___/|_| |_| \___|\___| + | ;--. + | (__ \ _____ _ _ + | | ) ) / ____| (_) | | + | |/ / | (___ ___ _ __ _ _ __ | |_ + | ( / \___ \ / __| '__| | '_ \| __| + | |/ ____) | (__| | | | |_) | |_ + | | |_____/ \___|_| |_| .__/ \__| + `-.._________..-' | | + |_| + + + CoffeeScript is a little language that compiles into JavaScript. + + Install Node.js, and then the CoffeeScript compiler: + sudo bin/cake install + + Or, if you have the Node Package Manager installed: + npm install -g coffee-script + (Leave off the -g if you don't wish to install globally.) + + Execute a script: + coffee /path/to/script.coffee + + Compile a script: + coffee -c /path/to/script.coffee + + For documentation, usage, and examples, see: + http://coffeescript.org/ + + To suggest a feature, report a bug, or general discussion: + http://github.com/jashkenas/coffee-script/issues/ + + If you'd like to chat, drop by #coffeescript on Freenode IRC, + or on webchat.freenode.net. + + The source repository: + git://github.com/jashkenas/coffee-script.git + + All contributors are listed here: + http://github.com/jashkenas/coffee-script/contributors diff --git a/node_modules/jade/node_modules/coffee-script/Rakefile b/node_modules/jade/node_modules/coffee-script/Rakefile new file mode 100644 index 0000000..dfb85da --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/Rakefile @@ -0,0 +1,78 @@ +require 'rubygems' +require 'erb' +require 'fileutils' +require 'rake/testtask' +require 'json' + +desc "Build the documentation page" +task :doc do + source = 'documentation/index.html.erb' + child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" } + at_exit { Process.kill("INT", child) } + Signal.trap("INT") { exit } + loop do + mtime = File.stat(source).mtime + if !@mtime || mtime > @mtime + rendered = ERB.new(File.read(source)).result(binding) + File.open('index.html', 'w+') {|f| f.write(rendered) } + end + @mtime = mtime + sleep 1 + end +end + +desc "Build coffee-script-source gem" +task :gem do + require 'rubygems' + require 'rubygems/package' + + gemspec = Gem::Specification.new do |s| + s.name = 'coffee-script-source' + s.version = JSON.parse(File.read('package.json'))["version"] + s.date = Time.now.strftime("%Y-%m-%d") + + s.homepage = "http://jashkenas.github.com/coffee-script/" + s.summary = "The CoffeeScript Compiler" + s.description = <<-EOS + CoffeeScript is a little language that compiles into JavaScript. + Underneath all of those embarrassing braces and semicolons, + JavaScript has always had a gorgeous object model at its heart. + CoffeeScript is an attempt to expose the good parts of JavaScript + in a simple way. + EOS + + s.files = [ + 'lib/coffee_script/coffee-script.js', + 'lib/coffee_script/source.rb' + ] + + s.authors = ['Jeremy Ashkenas'] + s.email = 'jashkenas@gmail.com' + s.rubyforge_project = 'coffee-script-source' + end + + file = File.open("coffee-script-source.gem", "w") + Gem::Package.open(file, 'w') do |pkg| + pkg.metadata = gemspec.to_yaml + + path = "lib/coffee_script/source.rb" + contents = <<-ERUBY +module CoffeeScript + module Source + def self.bundled_path + File.expand_path("../coffee-script.js", __FILE__) + end + end +end + ERUBY + pkg.add_file_simple(path, 0644, contents.size) do |tar_io| + tar_io.write(contents) + end + + contents = File.read("extras/coffee-script.js") + path = "lib/coffee_script/coffee-script.js" + pkg.add_file_simple(path, 0644, contents.size) do |tar_io| + tar_io.write(contents) + end + end +end diff --git a/node_modules/jade/node_modules/coffee-script/bin/cake b/node_modules/jade/node_modules/coffee-script/bin/cake new file mode 100755 index 0000000..5965f4e --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/bin/cake @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/cake').run(); diff --git a/node_modules/jade/node_modules/coffee-script/bin/coffee b/node_modules/jade/node_modules/coffee-script/bin/coffee new file mode 100755 index 0000000..3d1d71c --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/bin/coffee @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +var path = require('path'); +var fs = require('fs'); +var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib'); + +require(lib + '/coffee-script/command').run(); diff --git a/node_modules/jade/node_modules/coffee-script/extras/jsl.conf b/node_modules/jade/node_modules/coffee-script/extras/jsl.conf new file mode 100644 index 0000000..1190da5 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/extras/jsl.conf @@ -0,0 +1,44 @@ +# JavaScriptLint configuration file for CoffeeScript. + ++no_return_value # function {0} does not always return a value ++duplicate_formal # duplicate formal argument {0} +-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0} ++var_hides_arg # variable {0} hides argument ++redeclared_var # redeclaration of {0} {1} +-anon_no_return_value # anonymous function does not always return a value ++missing_semicolon # missing semicolon ++meaningless_block # meaningless block; curly braces have no impact +-comma_separated_stmts # multiple statements separated by commas (use semicolons?) ++unreachable_code # unreachable code ++missing_break # missing break statement +-missing_break_for_last_case # missing break statement for last case in switch +-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==) +-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement +-useless_void # use of the void type may be unnecessary (void is always undefined) ++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs ++use_of_label # use of label +-block_without_braces # block statement without curly braces ++leading_decimal_point # leading decimal point may indicate a number or an object member ++trailing_decimal_point # trailing decimal point may indicate a number or an object member ++octal_number # leading zeros make an octal number ++nested_comment # nested comment ++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma ++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement ++empty_statement # empty statement or extra semicolon +-missing_option_explicit # the "option explicit" control comment is missing ++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag ++dup_option_explicit # duplicate "option explicit" control comment ++useless_assign # useless assignment ++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity ++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent) +-missing_default_case # missing default case in switch statement ++duplicate_case_in_switch # duplicate case in switch statements ++default_not_at_end # the default case is not at the end of the switch statement ++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax ++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax ++useless_comparison # useless comparison; comparing identical expressions ++with_statement # with statement hides undeclared variables; use temporary variable instead ++trailing_comma_in_array # extra comma is not recommended in array initializers ++assign_to_function_call # assignment to a function call ++parseint_missing_radix # parseInt missing radix parameter ++lambda_assign_requires_semicolon diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/browser.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/browser.js new file mode 100644 index 0000000..045156f --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/browser.js @@ -0,0 +1,92 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var CoffeeScript, runScripts; + + CoffeeScript = require('./coffee-script'); + + CoffeeScript.require = require; + + CoffeeScript["eval"] = function(code, options) { + var _ref; + if (options == null) { + options = {}; + } + if ((_ref = options.bare) == null) { + options.bare = true; + } + return eval(CoffeeScript.compile(code, options)); + }; + + CoffeeScript.run = function(code, options) { + if (options == null) { + options = {}; + } + options.bare = true; + return Function(CoffeeScript.compile(code, options))(); + }; + + if (typeof window === "undefined" || window === null) { + return; + } + + CoffeeScript.load = function(url, callback) { + var xhr; + xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(); + xhr.open('GET', url, true); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + var _ref; + if (xhr.readyState === 4) { + if ((_ref = xhr.status) === 0 || _ref === 200) { + CoffeeScript.run(xhr.responseText); + } else { + throw new Error("Could not load " + url); + } + if (callback) { + return callback(); + } + } + }; + return xhr.send(null); + }; + + runScripts = function() { + var coffees, execute, index, length, s, scripts; + scripts = document.getElementsByTagName('script'); + coffees = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = scripts.length; _i < _len; _i++) { + s = scripts[_i]; + if (s.type === 'text/coffeescript') { + _results.push(s); + } + } + return _results; + })(); + index = 0; + length = coffees.length; + (execute = function() { + var script; + script = coffees[index++]; + if ((script != null ? script.type : void 0) === 'text/coffeescript') { + if (script.src) { + return CoffeeScript.load(script.src, execute); + } else { + CoffeeScript.run(script.innerHTML); + return execute(); + } + } + })(); + return null; + }; + + if (window.addEventListener) { + addEventListener('DOMContentLoaded', runScripts, false); + } else { + attachEvent('onload', runScripts); + } + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/cake.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/cake.js new file mode 100644 index 0000000..0e7f1cc --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/cake.js @@ -0,0 +1,113 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var CoffeeScript, cakefileDirectory, existsSync, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks; + + fs = require('fs'); + + path = require('path'); + + helpers = require('./helpers'); + + optparse = require('./optparse'); + + CoffeeScript = require('./coffee-script'); + + existsSync = fs.existsSync || path.existsSync; + + tasks = {}; + + options = {}; + + switches = []; + + oparse = null; + + helpers.extend(global, { + task: function(name, description, action) { + var _ref; + if (!action) { + _ref = [description, action], action = _ref[0], description = _ref[1]; + } + return tasks[name] = { + name: name, + description: description, + action: action + }; + }, + option: function(letter, flag, description) { + return switches.push([letter, flag, description]); + }, + invoke: function(name) { + if (!tasks[name]) { + missingTask(name); + } + return tasks[name].action(options); + } + }); + + exports.run = function() { + var arg, args, _i, _len, _ref, _results; + global.__originalDirname = fs.realpathSync('.'); + process.chdir(cakefileDirectory(__originalDirname)); + args = process.argv.slice(2); + CoffeeScript.run(fs.readFileSync('Cakefile').toString(), { + filename: 'Cakefile' + }); + oparse = new optparse.OptionParser(switches); + if (!args.length) { + return printTasks(); + } + try { + options = oparse.parse(args); + } catch (e) { + return fatalError("" + e); + } + _ref = options["arguments"]; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + arg = _ref[_i]; + _results.push(invoke(arg)); + } + return _results; + }; + + printTasks = function() { + var cakefilePath, desc, name, relative, spaces, task; + relative = path.relative || path.resolve; + cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile'); + console.log("" + cakefilePath + " defines the following tasks:\n"); + for (name in tasks) { + task = tasks[name]; + spaces = 20 - name.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + desc = task.description ? "# " + task.description : ''; + console.log("cake " + name + spaces + " " + desc); + } + if (switches.length) { + return console.log(oparse.help()); + } + }; + + fatalError = function(message) { + console.error(message + '\n'); + console.log('To see a list of all tasks/options, run "cake"'); + return process.exit(1); + }; + + missingTask = function(task) { + return fatalError("No such task: " + task); + }; + + cakefileDirectory = function(dir) { + var parent; + if (existsSync(path.join(dir, 'Cakefile'))) { + return dir; + } + parent = path.normalize(path.join(dir, '..')); + if (parent !== dir) { + return cakefileDirectory(parent); + } + throw new Error("Cakefile not found in " + (process.cwd())); + }; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/coffee-script.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/coffee-script.js new file mode 100644 index 0000000..7ee55cd --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/coffee-script.js @@ -0,0 +1,171 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var Lexer, RESERVED, compile, fs, lexer, parser, path, stripBOM, vm, _ref, + __hasProp = {}.hasOwnProperty; + + fs = require('fs'); + + path = require('path'); + + _ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED; + + parser = require('./parser').parser; + + vm = require('vm'); + + stripBOM = function(content) { + if (content.charCodeAt(0) === 0xFEFF) { + return content.substring(1); + } else { + return content; + } + }; + + if (require.extensions) { + require.extensions['.coffee'] = function(module, filename) { + var content; + content = compile(stripBOM(fs.readFileSync(filename, 'utf8')), { + filename: filename + }); + return module._compile(content, filename); + }; + } + + exports.VERSION = '1.4.0'; + + exports.RESERVED = RESERVED; + + exports.helpers = require('./helpers'); + + exports.compile = compile = function(code, options) { + var header, js, merge; + if (options == null) { + options = {}; + } + merge = exports.helpers.merge; + try { + js = (parser.parse(lexer.tokenize(code))).compile(options); + if (!options.header) { + return js; + } + } catch (err) { + if (options.filename) { + err.message = "In " + options.filename + ", " + err.message; + } + throw err; + } + header = "Generated by CoffeeScript " + this.VERSION; + return "// " + header + "\n" + js; + }; + + exports.tokens = function(code, options) { + return lexer.tokenize(code, options); + }; + + exports.nodes = function(source, options) { + if (typeof source === 'string') { + return parser.parse(lexer.tokenize(source, options)); + } else { + return parser.parse(source); + } + }; + + exports.run = function(code, options) { + var mainModule; + if (options == null) { + options = {}; + } + mainModule = require.main; + mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.'; + mainModule.moduleCache && (mainModule.moduleCache = {}); + mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename))); + if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) { + return mainModule._compile(compile(code, options), mainModule.filename); + } else { + return mainModule._compile(code, mainModule.filename); + } + }; + + exports["eval"] = function(code, options) { + var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref1, _ref2, _require; + if (options == null) { + options = {}; + } + if (!(code = code.trim())) { + return; + } + Script = vm.Script; + if (Script) { + if (options.sandbox != null) { + if (options.sandbox instanceof Script.createContext().constructor) { + sandbox = options.sandbox; + } else { + sandbox = Script.createContext(); + _ref1 = options.sandbox; + for (k in _ref1) { + if (!__hasProp.call(_ref1, k)) continue; + v = _ref1[k]; + sandbox[k] = v; + } + } + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; + } else { + sandbox = global; + } + sandbox.__filename = options.filename || 'eval'; + sandbox.__dirname = path.dirname(sandbox.__filename); + if (!(sandbox !== global || sandbox.module || sandbox.require)) { + Module = require('module'); + sandbox.module = _module = new Module(options.modulename || 'eval'); + sandbox.require = _require = function(path) { + return Module._load(path, _module, true); + }; + _module.filename = sandbox.__filename; + _ref2 = Object.getOwnPropertyNames(require); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + r = _ref2[_i]; + if (r !== 'paths') { + _require[r] = require[r]; + } + } + _require.paths = _module.paths = Module._nodeModulePaths(process.cwd()); + _require.resolve = function(request) { + return Module._resolveFilename(request, _module); + }; + } + } + o = {}; + for (k in options) { + if (!__hasProp.call(options, k)) continue; + v = options[k]; + o[k] = v; + } + o.bare = true; + js = compile(code, o); + if (sandbox === global) { + return vm.runInThisContext(js); + } else { + return vm.runInContext(js, sandbox); + } + }; + + lexer = new Lexer; + + parser.lexer = { + lex: function() { + var tag, _ref1; + _ref1 = this.tokens[this.pos++] || [''], tag = _ref1[0], this.yytext = _ref1[1], this.yylineno = _ref1[2]; + return tag; + }, + setInput: function(tokens) { + this.tokens = tokens; + return this.pos = 0; + }, + upcomingInput: function() { + return ""; + } + }; + + parser.yy = require('./nodes'); + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/command.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/command.js new file mode 100644 index 0000000..b0bcfe1 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/command.js @@ -0,0 +1,502 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, lint, loadRequires, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref; + + fs = require('fs'); + + path = require('path'); + + helpers = require('./helpers'); + + optparse = require('./optparse'); + + CoffeeScript = require('./coffee-script'); + + _ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec; + + EventEmitter = require('events').EventEmitter; + + exists = fs.exists || path.exists; + + helpers.extend(CoffeeScript, new EventEmitter); + + printLine = function(line) { + return process.stdout.write(line + '\n'); + }; + + printWarn = function(line) { + return process.stderr.write(line + '\n'); + }; + + hidden = function(file) { + return /^\.|~$/.test(file); + }; + + BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.'; + + SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']]; + + opts = {}; + + sources = []; + + sourceCode = []; + + notSources = {}; + + watchers = {}; + + optionParser = null; + + exports.run = function() { + var literals, source, _i, _len, _results; + parseOptions(); + if (opts.nodejs) { + return forkNode(); + } + if (opts.help) { + return usage(); + } + if (opts.version) { + return version(); + } + if (opts.require) { + loadRequires(); + } + if (opts.interactive) { + return require('./repl'); + } + if (opts.watch && !fs.watch) { + return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + "."); + } + if (opts.stdio) { + return compileStdio(); + } + if (opts["eval"]) { + return compileScript(null, sources[0]); + } + if (!sources.length) { + return require('./repl'); + } + literals = opts.run ? sources.splice(1) : []; + process.argv = process.argv.slice(0, 2).concat(literals); + process.argv[0] = 'coffee'; + process.execPath = require.main.filename; + _results = []; + for (_i = 0, _len = sources.length; _i < _len; _i++) { + source = sources[_i]; + _results.push(compilePath(source, true, path.normalize(source))); + } + return _results; + }; + + compilePath = function(source, topLevel, base) { + return fs.stat(source, function(err, stats) { + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + if (topLevel && source.slice(-7) !== '.coffee') { + source = sources[sources.indexOf(source)] = "" + source + ".coffee"; + return compilePath(source, topLevel, base); + } + if (topLevel) { + console.error("File not found: " + source); + process.exit(1); + } + return; + } + if (stats.isDirectory()) { + if (opts.watch) { + watchDir(source, base); + } + return fs.readdir(source, function(err, files) { + var file, index, _ref1, _ref2; + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + return; + } + index = sources.indexOf(source); + files = files.filter(function(file) { + return !hidden(file); + }); + [].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _results.push(path.join(source, file)); + } + return _results; + })())), _ref1; + [].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() { + return null; + }))), _ref2; + return files.forEach(function(file) { + return compilePath(path.join(source, file), false, base); + }); + }); + } else if (topLevel || path.extname(source) === '.coffee') { + if (opts.watch) { + watch(source, base); + } + return fs.readFile(source, function(err, code) { + if (err && err.code !== 'ENOENT') { + throw err; + } + if ((err != null ? err.code : void 0) === 'ENOENT') { + return; + } + return compileScript(source, code.toString(), base); + }); + } else { + notSources[source] = true; + return removeSource(source, base); + } + }); + }; + + compileScript = function(file, input, base) { + var o, options, t, task; + o = opts; + options = compileOptions(file); + try { + t = task = { + file: file, + input: input, + options: options + }; + CoffeeScript.emit('compile', task); + if (o.tokens) { + return printTokens(CoffeeScript.tokens(t.input)); + } else if (o.nodes) { + return printLine(CoffeeScript.nodes(t.input).toString().trim()); + } else if (o.run) { + return CoffeeScript.run(t.input, t.options); + } else if (o.join && t.file !== o.join) { + sourceCode[sources.indexOf(t.file)] = t.input; + return compileJoin(); + } else { + t.output = CoffeeScript.compile(t.input, t.options); + CoffeeScript.emit('success', task); + if (o.print) { + return printLine(t.output.trim()); + } else if (o.compile) { + return writeJs(t.file, t.output, base); + } else if (o.lint) { + return lint(t.file, t.output); + } + } + } catch (err) { + CoffeeScript.emit('failure', err, task); + if (CoffeeScript.listeners('failure').length) { + return; + } + if (o.watch) { + return printLine(err.message + '\x07'); + } + printWarn(err instanceof Error && err.stack || ("ERROR: " + err)); + return process.exit(1); + } + }; + + compileStdio = function() { + var code, stdin; + code = ''; + stdin = process.openStdin(); + stdin.on('data', function(buffer) { + if (buffer) { + return code += buffer.toString(); + } + }); + return stdin.on('end', function() { + return compileScript(null, code); + }); + }; + + joinTimeout = null; + + compileJoin = function() { + if (!opts.join) { + return; + } + if (!sourceCode.some(function(code) { + return code === null; + })) { + clearTimeout(joinTimeout); + return joinTimeout = wait(100, function() { + return compileScript(opts.join, sourceCode.join('\n'), opts.join); + }); + } + }; + + loadRequires = function() { + var realFilename, req, _i, _len, _ref1; + realFilename = module.filename; + module.filename = '.'; + _ref1 = opts.require; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + req = _ref1[_i]; + require(req); + } + return module.filename = realFilename; + }; + + watch = function(source, base) { + var compile, compileTimeout, prevStats, rewatch, watchErr, watcher; + prevStats = null; + compileTimeout = null; + watchErr = function(e) { + if (e.code === 'ENOENT') { + if (sources.indexOf(source) === -1) { + return; + } + try { + rewatch(); + return compile(); + } catch (e) { + removeSource(source, base, true); + return compileJoin(); + } + } else { + throw e; + } + }; + compile = function() { + clearTimeout(compileTimeout); + return compileTimeout = wait(25, function() { + return fs.stat(source, function(err, stats) { + if (err) { + return watchErr(err); + } + if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) { + return rewatch(); + } + prevStats = stats; + return fs.readFile(source, function(err, code) { + if (err) { + return watchErr(err); + } + compileScript(source, code.toString(), base); + return rewatch(); + }); + }); + }); + }; + try { + watcher = fs.watch(source, compile); + } catch (e) { + watchErr(e); + } + return rewatch = function() { + if (watcher != null) { + watcher.close(); + } + return watcher = fs.watch(source, compile); + }; + }; + + watchDir = function(source, base) { + var readdirTimeout, watcher; + readdirTimeout = null; + try { + return watcher = fs.watch(source, function() { + clearTimeout(readdirTimeout); + return readdirTimeout = wait(25, function() { + return fs.readdir(source, function(err, files) { + var file, _i, _len, _results; + if (err) { + if (err.code !== 'ENOENT') { + throw err; + } + watcher.close(); + return unwatchDir(source, base); + } + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + if (!(!hidden(file) && !notSources[file])) { + continue; + } + file = path.join(source, file); + if (sources.some(function(s) { + return s.indexOf(file) >= 0; + })) { + continue; + } + sources.push(file); + sourceCode.push(null); + _results.push(compilePath(file, false, base)); + } + return _results; + }); + }); + }); + } catch (e) { + if (e.code !== 'ENOENT') { + throw e; + } + } + }; + + unwatchDir = function(source, base) { + var file, prevSources, toRemove, _i, _len; + prevSources = sources.slice(0); + toRemove = (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = sources.length; _i < _len; _i++) { + file = sources[_i]; + if (file.indexOf(source) >= 0) { + _results.push(file); + } + } + return _results; + })(); + for (_i = 0, _len = toRemove.length; _i < _len; _i++) { + file = toRemove[_i]; + removeSource(file, base, true); + } + if (!sources.some(function(s, i) { + return prevSources[i] !== s; + })) { + return; + } + return compileJoin(); + }; + + removeSource = function(source, base, removeJs) { + var index, jsPath; + index = sources.indexOf(source); + sources.splice(index, 1); + sourceCode.splice(index, 1); + if (removeJs && !opts.join) { + jsPath = outputPath(source, base); + return exists(jsPath, function(itExists) { + if (itExists) { + return fs.unlink(jsPath, function(err) { + if (err && err.code !== 'ENOENT') { + throw err; + } + return timeLog("removed " + source); + }); + } + }); + } + }; + + outputPath = function(source, base) { + var baseDir, dir, filename, srcDir; + filename = path.basename(source, path.extname(source)) + '.js'; + srcDir = path.dirname(source); + baseDir = base === '.' ? srcDir : srcDir.substring(base.length); + dir = opts.output ? path.join(opts.output, baseDir) : srcDir; + return path.join(dir, filename); + }; + + writeJs = function(source, js, base) { + var compile, jsDir, jsPath; + jsPath = outputPath(source, base); + jsDir = path.dirname(jsPath); + compile = function() { + if (js.length <= 0) { + js = ' '; + } + return fs.writeFile(jsPath, js, function(err) { + if (err) { + return printLine(err.message); + } else if (opts.compile && opts.watch) { + return timeLog("compiled " + source); + } + }); + }; + return exists(jsDir, function(itExists) { + if (itExists) { + return compile(); + } else { + return exec("mkdir -p " + jsDir, compile); + } + }); + }; + + wait = function(milliseconds, func) { + return setTimeout(func, milliseconds); + }; + + timeLog = function(message) { + return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message); + }; + + lint = function(file, js) { + var conf, jsl, printIt; + printIt = function(buffer) { + return printLine(file + ':\t' + buffer.toString().trim()); + }; + conf = __dirname + '/../../extras/jsl.conf'; + jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]); + jsl.stdout.on('data', printIt); + jsl.stderr.on('data', printIt); + jsl.stdin.write(js); + return jsl.stdin.end(); + }; + + printTokens = function(tokens) { + var strings, tag, token, value; + strings = (function() { + var _i, _len, _ref1, _results; + _results = []; + for (_i = 0, _len = tokens.length; _i < _len; _i++) { + token = tokens[_i]; + _ref1 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref1[0], value = _ref1[1]; + _results.push("[" + tag + " " + value + "]"); + } + return _results; + })(); + return printLine(strings.join(' ')); + }; + + parseOptions = function() { + var i, o, source, _i, _len; + optionParser = new optparse.OptionParser(SWITCHES, BANNER); + o = opts = optionParser.parse(process.argv.slice(2)); + o.compile || (o.compile = !!o.output); + o.run = !(o.compile || o.print || o.lint); + o.print = !!(o.print || (o["eval"] || o.stdio && o.compile)); + sources = o["arguments"]; + for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) { + source = sources[i]; + sourceCode[i] = null; + } + }; + + compileOptions = function(filename) { + return { + filename: filename, + bare: opts.bare, + header: opts.compile + }; + }; + + forkNode = function() { + var args, nodeArgs; + nodeArgs = opts.nodejs.split(/\s+/); + args = process.argv.slice(1); + args.splice(args.indexOf('--nodejs'), 2); + return spawn(process.execPath, nodeArgs.concat(args), { + cwd: process.cwd(), + env: process.env, + customFds: [0, 1, 2] + }); + }; + + usage = function() { + return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help()); + }; + + version = function() { + return printLine("CoffeeScript version " + CoffeeScript.VERSION); + }; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/grammar.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/grammar.js new file mode 100644 index 0000000..e3513e5 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/grammar.js @@ -0,0 +1,606 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap; + + Parser = require('jison').Parser; + + unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/; + + o = function(patternString, action, options) { + var match; + patternString = patternString.replace(/\s{2,}/g, ' '); + if (!action) { + return [patternString, '$$ = $1;', options]; + } + action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())"; + action = action.replace(/\bnew /g, '$&yy.'); + action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&'); + return [patternString, "$$ = " + action + ";", options]; + }; + + grammar = { + Root: [ + o('', function() { + return new Block; + }), o('Body'), o('Block TERMINATOR') + ], + Body: [ + o('Line', function() { + return Block.wrap([$1]); + }), o('Body TERMINATOR Line', function() { + return $1.push($3); + }), o('Body TERMINATOR') + ], + Line: [o('Expression'), o('Statement')], + Statement: [ + o('Return'), o('Comment'), o('STATEMENT', function() { + return new Literal($1); + }) + ], + Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')], + Block: [ + o('INDENT OUTDENT', function() { + return new Block; + }), o('INDENT Body OUTDENT', function() { + return $2; + }) + ], + Identifier: [ + o('IDENTIFIER', function() { + return new Literal($1); + }) + ], + AlphaNumeric: [ + o('NUMBER', function() { + return new Literal($1); + }), o('STRING', function() { + return new Literal($1); + }) + ], + Literal: [ + o('AlphaNumeric'), o('JS', function() { + return new Literal($1); + }), o('REGEX', function() { + return new Literal($1); + }), o('DEBUGGER', function() { + return new Literal($1); + }), o('UNDEFINED', function() { + return new Undefined; + }), o('NULL', function() { + return new Null; + }), o('BOOL', function() { + return new Bool($1); + }) + ], + Assign: [ + o('Assignable = Expression', function() { + return new Assign($1, $3); + }), o('Assignable = TERMINATOR Expression', function() { + return new Assign($1, $4); + }), o('Assignable = INDENT Expression OUTDENT', function() { + return new Assign($1, $4); + }) + ], + AssignObj: [ + o('ObjAssignable', function() { + return new Value($1); + }), o('ObjAssignable : Expression', function() { + return new Assign(new Value($1), $3, 'object'); + }), o('ObjAssignable :\ + INDENT Expression OUTDENT', function() { + return new Assign(new Value($1), $4, 'object'); + }), o('Comment') + ], + ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')], + Return: [ + o('RETURN Expression', function() { + return new Return($2); + }), o('RETURN', function() { + return new Return; + }) + ], + Comment: [ + o('HERECOMMENT', function() { + return new Comment($1); + }) + ], + Code: [ + o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() { + return new Code($2, $5, $4); + }), o('FuncGlyph Block', function() { + return new Code([], $2, $1); + }) + ], + FuncGlyph: [ + o('->', function() { + return 'func'; + }), o('=>', function() { + return 'boundfunc'; + }) + ], + OptComma: [o(''), o(',')], + ParamList: [ + o('', function() { + return []; + }), o('Param', function() { + return [$1]; + }), o('ParamList , Param', function() { + return $1.concat($3); + }), o('ParamList OptComma TERMINATOR Param', function() { + return $1.concat($4); + }), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Param: [ + o('ParamVar', function() { + return new Param($1); + }), o('ParamVar ...', function() { + return new Param($1, null, true); + }), o('ParamVar = Expression', function() { + return new Param($1, $3); + }) + ], + ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')], + Splat: [ + o('Expression ...', function() { + return new Splat($1); + }) + ], + SimpleAssignable: [ + o('Identifier', function() { + return new Value($1); + }), o('Value Accessor', function() { + return $1.add($2); + }), o('Invocation Accessor', function() { + return new Value($1, [].concat($2)); + }), o('ThisProperty') + ], + Assignable: [ + o('SimpleAssignable'), o('Array', function() { + return new Value($1); + }), o('Object', function() { + return new Value($1); + }) + ], + Value: [ + o('Assignable'), o('Literal', function() { + return new Value($1); + }), o('Parenthetical', function() { + return new Value($1); + }), o('Range', function() { + return new Value($1); + }), o('This') + ], + Accessor: [ + o('. Identifier', function() { + return new Access($2); + }), o('?. Identifier', function() { + return new Access($2, 'soak'); + }), o(':: Identifier', function() { + return [new Access(new Literal('prototype')), new Access($2)]; + }), o('::', function() { + return new Access(new Literal('prototype')); + }), o('Index') + ], + Index: [ + o('INDEX_START IndexValue INDEX_END', function() { + return $2; + }), o('INDEX_SOAK Index', function() { + return extend($2, { + soak: true + }); + }) + ], + IndexValue: [ + o('Expression', function() { + return new Index($1); + }), o('Slice', function() { + return new Slice($1); + }) + ], + Object: [ + o('{ AssignList OptComma }', function() { + return new Obj($2, $1.generated); + }) + ], + AssignList: [ + o('', function() { + return []; + }), o('AssignObj', function() { + return [$1]; + }), o('AssignList , AssignObj', function() { + return $1.concat($3); + }), o('AssignList OptComma TERMINATOR AssignObj', function() { + return $1.concat($4); + }), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Class: [ + o('CLASS', function() { + return new Class; + }), o('CLASS Block', function() { + return new Class(null, null, $2); + }), o('CLASS EXTENDS Expression', function() { + return new Class(null, $3); + }), o('CLASS EXTENDS Expression Block', function() { + return new Class(null, $3, $4); + }), o('CLASS SimpleAssignable', function() { + return new Class($2); + }), o('CLASS SimpleAssignable Block', function() { + return new Class($2, null, $3); + }), o('CLASS SimpleAssignable EXTENDS Expression', function() { + return new Class($2, $4); + }), o('CLASS SimpleAssignable EXTENDS Expression Block', function() { + return new Class($2, $4, $5); + }) + ], + Invocation: [ + o('Value OptFuncExist Arguments', function() { + return new Call($1, $3, $2); + }), o('Invocation OptFuncExist Arguments', function() { + return new Call($1, $3, $2); + }), o('SUPER', function() { + return new Call('super', [new Splat(new Literal('arguments'))]); + }), o('SUPER Arguments', function() { + return new Call('super', $2); + }) + ], + OptFuncExist: [ + o('', function() { + return false; + }), o('FUNC_EXIST', function() { + return true; + }) + ], + Arguments: [ + o('CALL_START CALL_END', function() { + return []; + }), o('CALL_START ArgList OptComma CALL_END', function() { + return $2; + }) + ], + This: [ + o('THIS', function() { + return new Value(new Literal('this')); + }), o('@', function() { + return new Value(new Literal('this')); + }) + ], + ThisProperty: [ + o('@ Identifier', function() { + return new Value(new Literal('this'), [new Access($2)], 'this'); + }) + ], + Array: [ + o('[ ]', function() { + return new Arr([]); + }), o('[ ArgList OptComma ]', function() { + return new Arr($2); + }) + ], + RangeDots: [ + o('..', function() { + return 'inclusive'; + }), o('...', function() { + return 'exclusive'; + }) + ], + Range: [ + o('[ Expression RangeDots Expression ]', function() { + return new Range($2, $4, $3); + }) + ], + Slice: [ + o('Expression RangeDots Expression', function() { + return new Range($1, $3, $2); + }), o('Expression RangeDots', function() { + return new Range($1, null, $2); + }), o('RangeDots Expression', function() { + return new Range(null, $2, $1); + }), o('RangeDots', function() { + return new Range(null, null, $1); + }) + ], + ArgList: [ + o('Arg', function() { + return [$1]; + }), o('ArgList , Arg', function() { + return $1.concat($3); + }), o('ArgList OptComma TERMINATOR Arg', function() { + return $1.concat($4); + }), o('INDENT ArgList OptComma OUTDENT', function() { + return $2; + }), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() { + return $1.concat($4); + }) + ], + Arg: [o('Expression'), o('Splat')], + SimpleArgs: [ + o('Expression'), o('SimpleArgs , Expression', function() { + return [].concat($1, $3); + }) + ], + Try: [ + o('TRY Block', function() { + return new Try($2); + }), o('TRY Block Catch', function() { + return new Try($2, $3[0], $3[1]); + }), o('TRY Block FINALLY Block', function() { + return new Try($2, null, null, $4); + }), o('TRY Block Catch FINALLY Block', function() { + return new Try($2, $3[0], $3[1], $5); + }) + ], + Catch: [ + o('CATCH Identifier Block', function() { + return [$2, $3]; + }) + ], + Throw: [ + o('THROW Expression', function() { + return new Throw($2); + }) + ], + Parenthetical: [ + o('( Body )', function() { + return new Parens($2); + }), o('( INDENT Body OUTDENT )', function() { + return new Parens($3); + }) + ], + WhileSource: [ + o('WHILE Expression', function() { + return new While($2); + }), o('WHILE Expression WHEN Expression', function() { + return new While($2, { + guard: $4 + }); + }), o('UNTIL Expression', function() { + return new While($2, { + invert: true + }); + }), o('UNTIL Expression WHEN Expression', function() { + return new While($2, { + invert: true, + guard: $4 + }); + }) + ], + While: [ + o('WhileSource Block', function() { + return $1.addBody($2); + }), o('Statement WhileSource', function() { + return $2.addBody(Block.wrap([$1])); + }), o('Expression WhileSource', function() { + return $2.addBody(Block.wrap([$1])); + }), o('Loop', function() { + return $1; + }) + ], + Loop: [ + o('LOOP Block', function() { + return new While(new Literal('true')).addBody($2); + }), o('LOOP Expression', function() { + return new While(new Literal('true')).addBody(Block.wrap([$2])); + }) + ], + For: [ + o('Statement ForBody', function() { + return new For($1, $2); + }), o('Expression ForBody', function() { + return new For($1, $2); + }), o('ForBody Block', function() { + return new For($2, $1); + }) + ], + ForBody: [ + o('FOR Range', function() { + return { + source: new Value($2) + }; + }), o('ForStart ForSource', function() { + $2.own = $1.own; + $2.name = $1[0]; + $2.index = $1[1]; + return $2; + }) + ], + ForStart: [ + o('FOR ForVariables', function() { + return $2; + }), o('FOR OWN ForVariables', function() { + $3.own = true; + return $3; + }) + ], + ForValue: [ + o('Identifier'), o('ThisProperty'), o('Array', function() { + return new Value($1); + }), o('Object', function() { + return new Value($1); + }) + ], + ForVariables: [ + o('ForValue', function() { + return [$1]; + }), o('ForValue , ForValue', function() { + return [$1, $3]; + }) + ], + ForSource: [ + o('FORIN Expression', function() { + return { + source: $2 + }; + }), o('FOROF Expression', function() { + return { + source: $2, + object: true + }; + }), o('FORIN Expression WHEN Expression', function() { + return { + source: $2, + guard: $4 + }; + }), o('FOROF Expression WHEN Expression', function() { + return { + source: $2, + guard: $4, + object: true + }; + }), o('FORIN Expression BY Expression', function() { + return { + source: $2, + step: $4 + }; + }), o('FORIN Expression WHEN Expression BY Expression', function() { + return { + source: $2, + guard: $4, + step: $6 + }; + }), o('FORIN Expression BY Expression WHEN Expression', function() { + return { + source: $2, + step: $4, + guard: $6 + }; + }) + ], + Switch: [ + o('SWITCH Expression INDENT Whens OUTDENT', function() { + return new Switch($2, $4); + }), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() { + return new Switch($2, $4, $6); + }), o('SWITCH INDENT Whens OUTDENT', function() { + return new Switch(null, $3); + }), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() { + return new Switch(null, $3, $5); + }) + ], + Whens: [ + o('When'), o('Whens When', function() { + return $1.concat($2); + }) + ], + When: [ + o('LEADING_WHEN SimpleArgs Block', function() { + return [[$2, $3]]; + }), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() { + return [[$2, $3]]; + }) + ], + IfBlock: [ + o('IF Expression Block', function() { + return new If($2, $3, { + type: $1 + }); + }), o('IfBlock ELSE IF Expression Block', function() { + return $1.addElse(new If($4, $5, { + type: $3 + })); + }) + ], + If: [ + o('IfBlock'), o('IfBlock ELSE Block', function() { + return $1.addElse($3); + }), o('Statement POST_IF Expression', function() { + return new If($3, Block.wrap([$1]), { + type: $2, + statement: true + }); + }), o('Expression POST_IF Expression', function() { + return new If($3, Block.wrap([$1]), { + type: $2, + statement: true + }); + }) + ], + Operation: [ + o('UNARY Expression', function() { + return new Op($1, $2); + }), o('- Expression', (function() { + return new Op('-', $2); + }), { + prec: 'UNARY' + }), o('+ Expression', (function() { + return new Op('+', $2); + }), { + prec: 'UNARY' + }), o('-- SimpleAssignable', function() { + return new Op('--', $2); + }), o('++ SimpleAssignable', function() { + return new Op('++', $2); + }), o('SimpleAssignable --', function() { + return new Op('--', $1, null, true); + }), o('SimpleAssignable ++', function() { + return new Op('++', $1, null, true); + }), o('Expression ?', function() { + return new Existence($1); + }), o('Expression + Expression', function() { + return new Op('+', $1, $3); + }), o('Expression - Expression', function() { + return new Op('-', $1, $3); + }), o('Expression MATH Expression', function() { + return new Op($2, $1, $3); + }), o('Expression SHIFT Expression', function() { + return new Op($2, $1, $3); + }), o('Expression COMPARE Expression', function() { + return new Op($2, $1, $3); + }), o('Expression LOGIC Expression', function() { + return new Op($2, $1, $3); + }), o('Expression RELATION Expression', function() { + if ($2.charAt(0) === '!') { + return new Op($2.slice(1), $1, $3).invert(); + } else { + return new Op($2, $1, $3); + } + }), o('SimpleAssignable COMPOUND_ASSIGN\ + Expression', function() { + return new Assign($1, $3, $2); + }), o('SimpleAssignable COMPOUND_ASSIGN\ + INDENT Expression OUTDENT', function() { + return new Assign($1, $4, $2); + }), o('SimpleAssignable EXTENDS Expression', function() { + return new Extends($1, $3); + }) + ] + }; + + operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']]; + + tokens = []; + + for (name in grammar) { + alternatives = grammar[name]; + grammar[name] = (function() { + var _i, _j, _len, _len1, _ref, _results; + _results = []; + for (_i = 0, _len = alternatives.length; _i < _len; _i++) { + alt = alternatives[_i]; + _ref = alt[0].split(' '); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + token = _ref[_j]; + if (!grammar[token]) { + tokens.push(token); + } + } + if (name === 'Root') { + alt[1] = "return " + alt[1]; + } + _results.push(alt); + } + return _results; + })(); + } + + exports.parser = new Parser({ + tokens: tokens.join(' '), + bnf: grammar, + operators: operators.reverse(), + startSymbol: 'Root' + }); + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/helpers.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/helpers.js new file mode 100644 index 0000000..f9929f7 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/helpers.js @@ -0,0 +1,88 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var extend, flatten, _ref; + + exports.starts = function(string, literal, start) { + return literal === string.substr(start, literal.length); + }; + + exports.ends = function(string, literal, back) { + var len; + len = literal.length; + return literal === string.substr(string.length - len - (back || 0), len); + }; + + exports.compact = function(array) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + item = array[_i]; + if (item) { + _results.push(item); + } + } + return _results; + }; + + exports.count = function(string, substr) { + var num, pos; + num = pos = 0; + if (!substr.length) { + return 1 / 0; + } + while (pos = 1 + string.indexOf(substr, pos)) { + num++; + } + return num; + }; + + exports.merge = function(options, overrides) { + return extend(extend({}, options), overrides); + }; + + extend = exports.extend = function(object, properties) { + var key, val; + for (key in properties) { + val = properties[key]; + object[key] = val; + } + return object; + }; + + exports.flatten = flatten = function(array) { + var element, flattened, _i, _len; + flattened = []; + for (_i = 0, _len = array.length; _i < _len; _i++) { + element = array[_i]; + if (element instanceof Array) { + flattened = flattened.concat(flatten(element)); + } else { + flattened.push(element); + } + } + return flattened; + }; + + exports.del = function(obj, key) { + var val; + val = obj[key]; + delete obj[key]; + return val; + }; + + exports.last = function(array, back) { + return array[array.length - (back || 0) - 1]; + }; + + exports.some = (_ref = Array.prototype.some) != null ? _ref : function(fn) { + var e, _i, _len; + for (_i = 0, _len = this.length; _i < _len; _i++) { + e = this[_i]; + if (fn(e)) { + return true; + } + } + return false; + }; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/index.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/index.js new file mode 100644 index 0000000..b1c1765 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/index.js @@ -0,0 +1,11 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var key, val, _ref; + + _ref = require('./coffee-script'); + for (key in _ref) { + val = _ref[key]; + exports[key] = val; + } + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/lexer.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/lexer.js new file mode 100644 index 0000000..1b777cb --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/lexer.js @@ -0,0 +1,788 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES; + + _ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last; + + exports.Lexer = Lexer = (function() { + + function Lexer() {} + + Lexer.prototype.tokenize = function(code, opts) { + var i, tag; + if (opts == null) { + opts = {}; + } + if (WHITESPACE.test(code)) { + code = "\n" + code; + } + code = code.replace(/\r/g, '').replace(TRAILING_SPACES, ''); + this.code = code; + this.line = opts.line || 0; + this.indent = 0; + this.indebt = 0; + this.outdebt = 0; + this.indents = []; + this.ends = []; + this.tokens = []; + i = 0; + while (this.chunk = code.slice(i)) { + i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken(); + } + this.closeIndentation(); + if (tag = this.ends.pop()) { + this.error("missing " + tag); + } + if (opts.rewrite === false) { + return this.tokens; + } + return (new Rewriter).rewrite(this.tokens); + }; + + Lexer.prototype.identifierToken = function() { + var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3; + if (!(match = IDENTIFIER.exec(this.chunk))) { + return 0; + } + input = match[0], id = match[1], colon = match[2]; + if (id === 'own' && this.tag() === 'FOR') { + this.token('OWN', id); + return id.length; + } + forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@'); + tag = 'IDENTIFIER'; + if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) { + tag = id.toUpperCase(); + if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) { + tag = 'LEADING_WHEN'; + } else if (tag === 'FOR') { + this.seenFor = true; + } else if (tag === 'UNLESS') { + tag = 'IF'; + } else if (__indexOf.call(UNARY, tag) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(RELATION, tag) >= 0) { + if (tag !== 'INSTANCEOF' && this.seenFor) { + tag = 'FOR' + tag; + this.seenFor = false; + } else { + tag = 'RELATION'; + if (this.value() === '!') { + this.tokens.pop(); + id = '!' + id; + } + } + } + } + if (__indexOf.call(JS_FORBIDDEN, id) >= 0) { + if (forcedIdentifier) { + tag = 'IDENTIFIER'; + id = new String(id); + id.reserved = true; + } else if (__indexOf.call(RESERVED, id) >= 0) { + this.error("reserved word \"" + id + "\""); + } + } + if (!forcedIdentifier) { + if (__indexOf.call(COFFEE_ALIASES, id) >= 0) { + id = COFFEE_ALIAS_MAP[id]; + } + tag = (function() { + switch (id) { + case '!': + return 'UNARY'; + case '==': + case '!=': + return 'COMPARE'; + case '&&': + case '||': + return 'LOGIC'; + case 'true': + case 'false': + return 'BOOL'; + case 'break': + case 'continue': + return 'STATEMENT'; + default: + return tag; + } + })(); + } + this.token(tag, id); + if (colon) { + this.token(':', ':'); + } + return input.length; + }; + + Lexer.prototype.numberToken = function() { + var binaryLiteral, lexedLength, match, number, octalLiteral; + if (!(match = NUMBER.exec(this.chunk))) { + return 0; + } + number = match[0]; + if (/^0[BOX]/.test(number)) { + this.error("radix prefix '" + number + "' must be lowercase"); + } else if (/E/.test(number) && !/^0x/.test(number)) { + this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'"); + } else if (/^0\d*[89]/.test(number)) { + this.error("decimal literal '" + number + "' must not be prefixed with '0'"); + } else if (/^0\d+/.test(number)) { + this.error("octal literal '" + number + "' must be prefixed with '0o'"); + } + lexedLength = number.length; + if (octalLiteral = /^0o([0-7]+)/.exec(number)) { + number = '0x' + (parseInt(octalLiteral[1], 8)).toString(16); + } + if (binaryLiteral = /^0b([01]+)/.exec(number)) { + number = '0x' + (parseInt(binaryLiteral[1], 2)).toString(16); + } + this.token('NUMBER', number); + return lexedLength; + }; + + Lexer.prototype.stringToken = function() { + var match, octalEsc, string; + switch (this.chunk.charAt(0)) { + case "'": + if (!(match = SIMPLESTR.exec(this.chunk))) { + return 0; + } + this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n')); + break; + case '"': + if (!(string = this.balancedString(this.chunk, '"'))) { + return 0; + } + if (0 < string.indexOf('#{', 1)) { + this.interpolateString(string.slice(1, -1)); + } else { + this.token('STRING', this.escapeLines(string)); + } + break; + default: + return 0; + } + if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) { + this.error("octal escape sequences " + string + " are not allowed"); + } + this.line += count(string, '\n'); + return string.length; + }; + + Lexer.prototype.heredocToken = function() { + var doc, heredoc, match, quote; + if (!(match = HEREDOC.exec(this.chunk))) { + return 0; + } + heredoc = match[0]; + quote = heredoc.charAt(0); + doc = this.sanitizeHeredoc(match[2], { + quote: quote, + indent: null + }); + if (quote === '"' && 0 <= doc.indexOf('#{')) { + this.interpolateString(doc, { + heredoc: true + }); + } else { + this.token('STRING', this.makeString(doc, quote, true)); + } + this.line += count(heredoc, '\n'); + return heredoc.length; + }; + + Lexer.prototype.commentToken = function() { + var comment, here, match; + if (!(match = this.chunk.match(COMMENT))) { + return 0; + } + comment = match[0], here = match[1]; + if (here) { + this.token('HERECOMMENT', this.sanitizeHeredoc(here, { + herecomment: true, + indent: Array(this.indent + 1).join(' ') + })); + } + this.line += count(comment, '\n'); + return comment.length; + }; + + Lexer.prototype.jsToken = function() { + var match, script; + if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) { + return 0; + } + this.token('JS', (script = match[0]).slice(1, -1)); + this.line += count(script, '\n'); + return script.length; + }; + + Lexer.prototype.regexToken = function() { + var flags, length, match, prev, regex, _ref2, _ref3; + if (this.chunk.charAt(0) !== '/') { + return 0; + } + if (match = HEREGEX.exec(this.chunk)) { + length = this.heregexToken(match); + this.line += count(match[0], '\n'); + return length; + } + prev = last(this.tokens); + if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) { + return 0; + } + if (!(match = REGEX.exec(this.chunk))) { + return 0; + } + _ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2]; + if (regex.slice(0, 2) === '/*') { + this.error('regular expressions cannot begin with `*`'); + } + if (regex === '//') { + regex = '/(?:)/'; + } + this.token('REGEX', "" + regex + flags); + return match.length; + }; + + Lexer.prototype.heregexToken = function(match) { + var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5; + heregex = match[0], body = match[1], flags = match[2]; + if (0 > body.indexOf('#{')) { + re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/'); + if (re.match(/^\*/)) { + this.error('regular expressions cannot begin with `*`'); + } + this.token('REGEX', "/" + (re || '(?:)') + "/" + flags); + return heregex.length; + } + this.token('IDENTIFIER', 'RegExp'); + this.tokens.push(['CALL_START', '(']); + tokens = []; + _ref2 = this.interpolateString(body, { + regex: true + }); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1]; + if (tag === 'TOKENS') { + tokens.push.apply(tokens, value); + } else { + if (!(value = value.replace(HEREGEX_OMIT, ''))) { + continue; + } + value = value.replace(/\\/g, '\\\\'); + tokens.push(['STRING', this.makeString(value, '"', true)]); + } + tokens.push(['+', '+']); + } + tokens.pop(); + if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') { + this.tokens.push(['STRING', '""'], ['+', '+']); + } + (_ref5 = this.tokens).push.apply(_ref5, tokens); + if (flags) { + this.tokens.push([',', ','], ['STRING', '"' + flags + '"']); + } + this.token(')', ')'); + return heregex.length; + }; + + Lexer.prototype.lineToken = function() { + var diff, indent, match, noNewlines, size; + if (!(match = MULTI_DENT.exec(this.chunk))) { + return 0; + } + indent = match[0]; + this.line += count(indent, '\n'); + this.seenFor = false; + size = indent.length - 1 - indent.lastIndexOf('\n'); + noNewlines = this.unfinished(); + if (size - this.indebt === this.indent) { + if (noNewlines) { + this.suppressNewlines(); + } else { + this.newlineToken(); + } + return indent.length; + } + if (size > this.indent) { + if (noNewlines) { + this.indebt = size - this.indent; + this.suppressNewlines(); + return indent.length; + } + diff = size - this.indent + this.outdebt; + this.token('INDENT', diff); + this.indents.push(diff); + this.ends.push('OUTDENT'); + this.outdebt = this.indebt = 0; + } else { + this.indebt = 0; + this.outdentToken(this.indent - size, noNewlines); + } + this.indent = size; + return indent.length; + }; + + Lexer.prototype.outdentToken = function(moveOut, noNewlines) { + var dent, len; + while (moveOut > 0) { + len = this.indents.length - 1; + if (this.indents[len] === void 0) { + moveOut = 0; + } else if (this.indents[len] === this.outdebt) { + moveOut -= this.outdebt; + this.outdebt = 0; + } else if (this.indents[len] < this.outdebt) { + this.outdebt -= this.indents[len]; + moveOut -= this.indents[len]; + } else { + dent = this.indents.pop() - this.outdebt; + moveOut -= dent; + this.outdebt = 0; + this.pair('OUTDENT'); + this.token('OUTDENT', dent); + } + } + if (dent) { + this.outdebt -= moveOut; + } + while (this.value() === ';') { + this.tokens.pop(); + } + if (!(this.tag() === 'TERMINATOR' || noNewlines)) { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.whitespaceToken = function() { + var match, nline, prev; + if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) { + return 0; + } + prev = last(this.tokens); + if (prev) { + prev[match ? 'spaced' : 'newLine'] = true; + } + if (match) { + return match[0].length; + } else { + return 0; + } + }; + + Lexer.prototype.newlineToken = function() { + while (this.value() === ';') { + this.tokens.pop(); + } + if (this.tag() !== 'TERMINATOR') { + this.token('TERMINATOR', '\n'); + } + return this; + }; + + Lexer.prototype.suppressNewlines = function() { + if (this.value() === '\\') { + this.tokens.pop(); + } + return this; + }; + + Lexer.prototype.literalToken = function() { + var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5; + if (match = OPERATOR.exec(this.chunk)) { + value = match[0]; + if (CODE.test(value)) { + this.tagParameters(); + } + } else { + value = this.chunk.charAt(0); + } + tag = value; + prev = last(this.tokens); + if (value === '=' && prev) { + if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) { + this.error("reserved word \"" + (this.value()) + "\" can't be assigned"); + } + if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') { + prev[0] = 'COMPOUND_ASSIGN'; + prev[1] += '='; + return value.length; + } + } + if (value === ';') { + this.seenFor = false; + tag = 'TERMINATOR'; + } else if (__indexOf.call(MATH, value) >= 0) { + tag = 'MATH'; + } else if (__indexOf.call(COMPARE, value) >= 0) { + tag = 'COMPARE'; + } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) { + tag = 'COMPOUND_ASSIGN'; + } else if (__indexOf.call(UNARY, value) >= 0) { + tag = 'UNARY'; + } else if (__indexOf.call(SHIFT, value) >= 0) { + tag = 'SHIFT'; + } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) { + tag = 'LOGIC'; + } else if (prev && !prev.spaced) { + if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) { + if (prev[0] === '?') { + prev[0] = 'FUNC_EXIST'; + } + tag = 'CALL_START'; + } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) { + tag = 'INDEX_START'; + switch (prev[0]) { + case '?': + prev[0] = 'INDEX_SOAK'; + } + } + } + switch (value) { + case '(': + case '{': + case '[': + this.ends.push(INVERSES[value]); + break; + case ')': + case '}': + case ']': + this.pair(value); + } + this.token(tag, value); + return value.length; + }; + + Lexer.prototype.sanitizeHeredoc = function(doc, options) { + var attempt, herecomment, indent, match, _ref2; + indent = options.indent, herecomment = options.herecomment; + if (herecomment) { + if (HEREDOC_ILLEGAL.test(doc)) { + this.error("block comment cannot contain \"*/\", starting"); + } + if (doc.indexOf('\n') <= 0) { + return doc; + } + } else { + while (match = HEREDOC_INDENT.exec(doc)) { + attempt = match[1]; + if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) { + indent = attempt; + } + } + } + if (indent) { + doc = doc.replace(RegExp("\\n" + indent, "g"), '\n'); + } + if (!herecomment) { + doc = doc.replace(/^\n/, ''); + } + return doc; + }; + + Lexer.prototype.tagParameters = function() { + var i, stack, tok, tokens; + if (this.tag() !== ')') { + return this; + } + stack = []; + tokens = this.tokens; + i = tokens.length; + tokens[--i][0] = 'PARAM_END'; + while (tok = tokens[--i]) { + switch (tok[0]) { + case ')': + stack.push(tok); + break; + case '(': + case 'CALL_START': + if (stack.length) { + stack.pop(); + } else if (tok[0] === '(') { + tok[0] = 'PARAM_START'; + return this; + } else { + return this; + } + } + } + return this; + }; + + Lexer.prototype.closeIndentation = function() { + return this.outdentToken(this.indent); + }; + + Lexer.prototype.balancedString = function(str, end) { + var continueCount, i, letter, match, prev, stack, _i, _ref2; + continueCount = 0; + stack = [end]; + for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) { + if (continueCount) { + --continueCount; + continue; + } + switch (letter = str.charAt(i)) { + case '\\': + ++continueCount; + continue; + case end: + stack.pop(); + if (!stack.length) { + return str.slice(0, +i + 1 || 9e9); + } + end = stack[stack.length - 1]; + continue; + } + if (end === '}' && (letter === '"' || letter === "'")) { + stack.push(end = letter); + } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) { + continueCount += match[0].length - 1; + } else if (end === '}' && letter === '{') { + stack.push(end = '}'); + } else if (end === '"' && prev === '#' && letter === '{') { + stack.push(end = '}'); + } + prev = letter; + } + return this.error("missing " + (stack.pop()) + ", starting"); + }; + + Lexer.prototype.interpolateString = function(str, options) { + var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4; + if (options == null) { + options = {}; + } + heredoc = options.heredoc, regex = options.regex; + tokens = []; + pi = 0; + i = -1; + while (letter = str.charAt(i += 1)) { + if (letter === '\\') { + i += 1; + continue; + } + if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) { + continue; + } + if (pi < i) { + tokens.push(['NEOSTRING', str.slice(pi, i)]); + } + inner = expr.slice(1, -1); + if (inner.length) { + nested = new Lexer().tokenize(inner, { + line: this.line, + rewrite: false + }); + nested.pop(); + if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') { + nested.shift(); + } + if (len = nested.length) { + if (len > 1) { + nested.unshift(['(', '(', this.line]); + nested.push([')', ')', this.line]); + } + tokens.push(['TOKENS', nested]); + } + } + i += expr.length; + pi = i + 1; + } + if ((i > pi && pi < str.length)) { + tokens.push(['NEOSTRING', str.slice(pi)]); + } + if (regex) { + return tokens; + } + if (!tokens.length) { + return this.token('STRING', '""'); + } + if (tokens[0][0] !== 'NEOSTRING') { + tokens.unshift(['', '']); + } + if (interpolated = tokens.length > 1) { + this.token('(', '('); + } + for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) { + _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1]; + if (i) { + this.token('+', '+'); + } + if (tag === 'TOKENS') { + (_ref4 = this.tokens).push.apply(_ref4, value); + } else { + this.token('STRING', this.makeString(value, '"', heredoc)); + } + } + if (interpolated) { + this.token(')', ')'); + } + return tokens; + }; + + Lexer.prototype.pair = function(tag) { + var size, wanted; + if (tag !== (wanted = last(this.ends))) { + if ('OUTDENT' !== wanted) { + this.error("unmatched " + tag); + } + this.indent -= size = last(this.indents); + this.outdentToken(size, true); + return this.pair(tag); + } + return this.ends.pop(); + }; + + Lexer.prototype.token = function(tag, value) { + return this.tokens.push([tag, value, this.line]); + }; + + Lexer.prototype.tag = function(index, tag) { + var tok; + return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]); + }; + + Lexer.prototype.value = function(index, val) { + var tok; + return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]); + }; + + Lexer.prototype.unfinished = function() { + var _ref2; + return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS'); + }; + + Lexer.prototype.escapeLines = function(str, heredoc) { + return str.replace(MULTILINER, heredoc ? '\\n' : ''); + }; + + Lexer.prototype.makeString = function(body, quote, heredoc) { + if (!body) { + return quote + quote; + } + body = body.replace(/\\([\s\S])/g, function(match, contents) { + if (contents === '\n' || contents === quote) { + return contents; + } else { + return match; + } + }); + body = body.replace(RegExp("" + quote, "g"), '\\$&'); + return quote + this.escapeLines(body, heredoc) + quote; + }; + + Lexer.prototype.error = function(message) { + throw SyntaxError("" + message + " on line " + (this.line + 1)); + }; + + return Lexer; + + })(); + + JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super']; + + COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']; + + COFFEE_ALIAS_MAP = { + and: '&&', + or: '||', + is: '==', + isnt: '!=', + not: '!', + yes: 'true', + no: 'false', + on: 'true', + off: 'false' + }; + + COFFEE_ALIASES = (function() { + var _results; + _results = []; + for (key in COFFEE_ALIAS_MAP) { + _results.push(key); + } + return _results; + })(); + + COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES); + + RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'package', 'private', 'protected', 'public', 'static', 'yield']; + + STRICT_PROSCRIBED = ['arguments', 'eval']; + + JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED); + + exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED); + + exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED; + + IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/; + + NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; + + HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/; + + OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/; + + WHITESPACE = /^[^\n\S]+/; + + COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/; + + CODE = /^[-=]>/; + + MULTI_DENT = /^(?:\n[^\n\S]*)+/; + + SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/; + + JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; + + REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/; + + HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/; + + HEREGEX_OMIT = /\s+(?:#.*)?/g; + + MULTILINER = /\n/g; + + HEREDOC_INDENT = /\n+([^\n\S]*)/g; + + HEREDOC_ILLEGAL = /\*\//; + + LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/; + + TRAILING_SPACES = /\s+$/; + + COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']; + + UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO']; + + LOGIC = ['&&', '||', '&', '|', '^']; + + SHIFT = ['<<', '>>', '>>>']; + + COMPARE = ['==', '!=', '<', '>', '<=', '>=']; + + MATH = ['*', '/', '%']; + + RELATION = ['IN', 'OF', 'INSTANCEOF']; + + BOOL = ['TRUE', 'FALSE']; + + NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']; + + NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING'); + + CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']; + + INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL', 'NULL', 'UNDEFINED'); + + LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/nodes.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/nodes.js new file mode 100644 index 0000000..f8e0777 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/nodes.js @@ -0,0 +1,2971 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, some, starts, unfoldSoak, utility, _ref, _ref1, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + Scope = require('./scope').Scope; + + _ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED; + + _ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last, some = _ref1.some; + + exports.extend = extend; + + YES = function() { + return true; + }; + + NO = function() { + return false; + }; + + THIS = function() { + return this; + }; + + NEGATE = function() { + this.negated = !this.negated; + return this; + }; + + exports.Base = Base = (function() { + + function Base() {} + + Base.prototype.compile = function(o, lvl) { + var node; + o = extend({}, o); + if (lvl) { + o.level = lvl; + } + node = this.unfoldSoak(o) || this; + node.tab = o.indent; + if (o.level === LEVEL_TOP || !node.isStatement(o)) { + return node.compileNode(o); + } else { + return node.compileClosure(o); + } + }; + + Base.prototype.compileClosure = function(o) { + if (this.jumps()) { + throw SyntaxError('cannot use a pure statement in an expression.'); + } + o.sharedScope = true; + return Closure.wrap(this).compileNode(o); + }; + + Base.prototype.cache = function(o, level, reused) { + var ref, sub; + if (!this.isComplex()) { + ref = level ? this.compile(o, level) : this; + return [ref, ref]; + } else { + ref = new Literal(reused || o.scope.freeVariable('ref')); + sub = new Assign(ref, this); + if (level) { + return [sub.compile(o, level), ref.value]; + } else { + return [sub, ref]; + } + } + }; + + Base.prototype.compileLoopReference = function(o, name) { + var src, tmp; + src = tmp = this.compile(o, LEVEL_LIST); + if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) { + src = "" + (tmp = o.scope.freeVariable(name)) + " = " + src; + } + return [src, tmp]; + }; + + Base.prototype.makeReturn = function(res) { + var me; + me = this.unwrapAll(); + if (res) { + return new Call(new Literal("" + res + ".push"), [me]); + } else { + return new Return(me); + } + }; + + Base.prototype.contains = function(pred) { + var contains; + contains = false; + this.traverseChildren(false, function(node) { + if (pred(node)) { + contains = true; + return false; + } + }); + return contains; + }; + + Base.prototype.containsType = function(type) { + return this instanceof type || this.contains(function(node) { + return node instanceof type; + }); + }; + + Base.prototype.lastNonComment = function(list) { + var i; + i = list.length; + while (i--) { + if (!(list[i] instanceof Comment)) { + return list[i]; + } + } + return null; + }; + + Base.prototype.toString = function(idt, name) { + var tree; + if (idt == null) { + idt = ''; + } + if (name == null) { + name = this.constructor.name; + } + tree = '\n' + idt + name; + if (this.soak) { + tree += '?'; + } + this.eachChild(function(node) { + return tree += node.toString(idt + TAB); + }); + return tree; + }; + + Base.prototype.eachChild = function(func) { + var attr, child, _i, _j, _len, _len1, _ref2, _ref3; + if (!this.children) { + return this; + } + _ref2 = this.children; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + attr = _ref2[_i]; + if (this[attr]) { + _ref3 = flatten([this[attr]]); + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + child = _ref3[_j]; + if (func(child) === false) { + return this; + } + } + } + } + return this; + }; + + Base.prototype.traverseChildren = function(crossScope, func) { + return this.eachChild(function(child) { + if (func(child) === false) { + return false; + } + return child.traverseChildren(crossScope, func); + }); + }; + + Base.prototype.invert = function() { + return new Op('!', this); + }; + + Base.prototype.unwrapAll = function() { + var node; + node = this; + while (node !== (node = node.unwrap())) { + continue; + } + return node; + }; + + Base.prototype.children = []; + + Base.prototype.isStatement = NO; + + Base.prototype.jumps = NO; + + Base.prototype.isComplex = YES; + + Base.prototype.isChainable = NO; + + Base.prototype.isAssignable = NO; + + Base.prototype.unwrap = THIS; + + Base.prototype.unfoldSoak = NO; + + Base.prototype.assigns = NO; + + return Base; + + })(); + + exports.Block = Block = (function(_super) { + + __extends(Block, _super); + + function Block(nodes) { + this.expressions = compact(flatten(nodes || [])); + } + + Block.prototype.children = ['expressions']; + + Block.prototype.push = function(node) { + this.expressions.push(node); + return this; + }; + + Block.prototype.pop = function() { + return this.expressions.pop(); + }; + + Block.prototype.unshift = function(node) { + this.expressions.unshift(node); + return this; + }; + + Block.prototype.unwrap = function() { + if (this.expressions.length === 1) { + return this.expressions[0]; + } else { + return this; + } + }; + + Block.prototype.isEmpty = function() { + return !this.expressions.length; + }; + + Block.prototype.isStatement = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.isStatement(o)) { + return true; + } + } + return false; + }; + + Block.prototype.jumps = function(o) { + var exp, _i, _len, _ref2; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + exp = _ref2[_i]; + if (exp.jumps(o)) { + return exp; + } + } + }; + + Block.prototype.makeReturn = function(res) { + var expr, len; + len = this.expressions.length; + while (len--) { + expr = this.expressions[len]; + if (!(expr instanceof Comment)) { + this.expressions[len] = expr.makeReturn(res); + if (expr instanceof Return && !expr.expression) { + this.expressions.splice(len, 1); + } + break; + } + } + return this; + }; + + Block.prototype.compile = function(o, level) { + if (o == null) { + o = {}; + } + if (o.scope) { + return Block.__super__.compile.call(this, o, level); + } else { + return this.compileRoot(o); + } + }; + + Block.prototype.compileNode = function(o) { + var code, codes, node, top, _i, _len, _ref2; + this.tab = o.indent; + top = o.level === LEVEL_TOP; + codes = []; + _ref2 = this.expressions; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + node = node.unwrapAll(); + node = node.unfoldSoak(o) || node; + if (node instanceof Block) { + codes.push(node.compileNode(o)); + } else if (top) { + node.front = true; + code = node.compile(o); + if (!node.isStatement(o)) { + code = "" + this.tab + code + ";"; + if (node instanceof Literal) { + code = "" + code + "\n"; + } + } + codes.push(code); + } else { + codes.push(node.compile(o, LEVEL_LIST)); + } + } + if (top) { + if (this.spaced) { + return "\n" + (codes.join('\n\n')) + "\n"; + } else { + return codes.join('\n'); + } + } + code = codes.join(', ') || 'void 0'; + if (codes.length > 1 && o.level >= LEVEL_LIST) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Block.prototype.compileRoot = function(o) { + var code, exp, i, prelude, preludeExps, rest; + o.indent = o.bare ? '' : TAB; + o.scope = new Scope(null, this, null); + o.level = LEVEL_TOP; + this.spaced = true; + prelude = ""; + if (!o.bare) { + preludeExps = (function() { + var _i, _len, _ref2, _results; + _ref2 = this.expressions; + _results = []; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + if (!(exp.unwrap() instanceof Comment)) { + break; + } + _results.push(exp); + } + return _results; + }).call(this); + rest = this.expressions.slice(preludeExps.length); + this.expressions = preludeExps; + if (preludeExps.length) { + prelude = "" + (this.compileNode(merge(o, { + indent: '' + }))) + "\n"; + } + this.expressions = rest; + } + code = this.compileWithDeclarations(o); + if (o.bare) { + return code; + } + return "" + prelude + "(function() {\n" + code + "\n}).call(this);\n"; + }; + + Block.prototype.compileWithDeclarations = function(o) { + var assigns, code, declars, exp, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4; + code = post = ''; + _ref2 = this.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + exp = _ref2[i]; + exp = exp.unwrap(); + if (!(exp instanceof Comment || exp instanceof Literal)) { + break; + } + } + o = merge(o, { + level: LEVEL_TOP + }); + if (i) { + rest = this.expressions.splice(i, 9e9); + _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1]; + _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1]; + this.expressions = rest; + } + post = this.compileNode(o); + scope = o.scope; + if (scope.expressions === this) { + declars = o.scope.hasDeclarations(); + assigns = scope.hasAssignments; + if (declars || assigns) { + if (i) { + code += '\n'; + } + code += "" + this.tab + "var "; + if (declars) { + code += scope.declaredVariables().join(', '); + } + if (assigns) { + if (declars) { + code += ",\n" + (this.tab + TAB); + } + code += scope.assignedVariables().join(",\n" + (this.tab + TAB)); + } + code += ';\n'; + } + } + return code + post; + }; + + Block.wrap = function(nodes) { + if (nodes.length === 1 && nodes[0] instanceof Block) { + return nodes[0]; + } + return new Block(nodes); + }; + + return Block; + + })(Base); + + exports.Literal = Literal = (function(_super) { + + __extends(Literal, _super); + + function Literal(value) { + this.value = value; + } + + Literal.prototype.makeReturn = function() { + if (this.isStatement()) { + return this; + } else { + return Literal.__super__.makeReturn.apply(this, arguments); + } + }; + + Literal.prototype.isAssignable = function() { + return IDENTIFIER.test(this.value); + }; + + Literal.prototype.isStatement = function() { + var _ref2; + return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger'; + }; + + Literal.prototype.isComplex = NO; + + Literal.prototype.assigns = function(name) { + return name === this.value; + }; + + Literal.prototype.jumps = function(o) { + if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) { + return this; + } + if (this.value === 'continue' && !(o != null ? o.loop : void 0)) { + return this; + } + }; + + Literal.prototype.compileNode = function(o) { + var code, _ref2; + code = this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value; + if (this.isStatement()) { + return "" + this.tab + code + ";"; + } else { + return code; + } + }; + + Literal.prototype.toString = function() { + return ' "' + this.value + '"'; + }; + + return Literal; + + })(Base); + + exports.Undefined = (function(_super) { + + __extends(Undefined, _super); + + function Undefined() { + return Undefined.__super__.constructor.apply(this, arguments); + } + + Undefined.prototype.isAssignable = NO; + + Undefined.prototype.isComplex = NO; + + Undefined.prototype.compileNode = function(o) { + if (o.level >= LEVEL_ACCESS) { + return '(void 0)'; + } else { + return 'void 0'; + } + }; + + return Undefined; + + })(Base); + + exports.Null = (function(_super) { + + __extends(Null, _super); + + function Null() { + return Null.__super__.constructor.apply(this, arguments); + } + + Null.prototype.isAssignable = NO; + + Null.prototype.isComplex = NO; + + Null.prototype.compileNode = function() { + return "null"; + }; + + return Null; + + })(Base); + + exports.Bool = (function(_super) { + + __extends(Bool, _super); + + Bool.prototype.isAssignable = NO; + + Bool.prototype.isComplex = NO; + + Bool.prototype.compileNode = function() { + return this.val; + }; + + function Bool(val) { + this.val = val; + } + + return Bool; + + })(Base); + + exports.Return = Return = (function(_super) { + + __extends(Return, _super); + + function Return(expr) { + if (expr && !expr.unwrap().isUndefined) { + this.expression = expr; + } + } + + Return.prototype.children = ['expression']; + + Return.prototype.isStatement = YES; + + Return.prototype.makeReturn = THIS; + + Return.prototype.jumps = THIS; + + Return.prototype.compile = function(o, level) { + var expr, _ref2; + expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0; + if (expr && !(expr instanceof Return)) { + return expr.compile(o, level); + } else { + return Return.__super__.compile.call(this, o, level); + } + }; + + Return.prototype.compileNode = function(o) { + return this.tab + ("return" + [this.expression ? " " + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + ";"); + }; + + return Return; + + })(Base); + + exports.Value = Value = (function(_super) { + + __extends(Value, _super); + + function Value(base, props, tag) { + if (!props && base instanceof Value) { + return base; + } + this.base = base; + this.properties = props || []; + if (tag) { + this[tag] = true; + } + return this; + } + + Value.prototype.children = ['base', 'properties']; + + Value.prototype.add = function(props) { + this.properties = this.properties.concat(props); + return this; + }; + + Value.prototype.hasProperties = function() { + return !!this.properties.length; + }; + + Value.prototype.isArray = function() { + return !this.properties.length && this.base instanceof Arr; + }; + + Value.prototype.isComplex = function() { + return this.hasProperties() || this.base.isComplex(); + }; + + Value.prototype.isAssignable = function() { + return this.hasProperties() || this.base.isAssignable(); + }; + + Value.prototype.isSimpleNumber = function() { + return this.base instanceof Literal && SIMPLENUM.test(this.base.value); + }; + + Value.prototype.isString = function() { + return this.base instanceof Literal && IS_STRING.test(this.base.value); + }; + + Value.prototype.isAtomic = function() { + var node, _i, _len, _ref2; + _ref2 = this.properties.concat(this.base); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + node = _ref2[_i]; + if (node.soak || node instanceof Call) { + return false; + } + } + return true; + }; + + Value.prototype.isStatement = function(o) { + return !this.properties.length && this.base.isStatement(o); + }; + + Value.prototype.assigns = function(name) { + return !this.properties.length && this.base.assigns(name); + }; + + Value.prototype.jumps = function(o) { + return !this.properties.length && this.base.jumps(o); + }; + + Value.prototype.isObject = function(onlyGenerated) { + if (this.properties.length) { + return false; + } + return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated); + }; + + Value.prototype.isSplice = function() { + return last(this.properties) instanceof Slice; + }; + + Value.prototype.unwrap = function() { + if (this.properties.length) { + return this; + } else { + return this.base; + } + }; + + Value.prototype.cacheReference = function(o) { + var base, bref, name, nref; + name = last(this.properties); + if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) { + return [this, this]; + } + base = new Value(this.base, this.properties.slice(0, -1)); + if (base.isComplex()) { + bref = new Literal(o.scope.freeVariable('base')); + base = new Value(new Parens(new Assign(bref, base))); + } + if (!name) { + return [base, bref]; + } + if (name.isComplex()) { + nref = new Literal(o.scope.freeVariable('name')); + name = new Index(new Assign(nref, name.index)); + nref = new Index(nref); + } + return [base.add(name), new Value(bref || base.base, [nref || name])]; + }; + + Value.prototype.compileNode = function(o) { + var code, prop, props, _i, _len; + this.base.front = this.front; + props = this.properties; + code = this.base.compile(o, props.length ? LEVEL_ACCESS : null); + if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) { + code = "" + code + "."; + } + for (_i = 0, _len = props.length; _i < _len; _i++) { + prop = props[_i]; + code += prop.compile(o); + } + return code; + }; + + Value.prototype.unfoldSoak = function(o) { + var result, + _this = this; + if (this.unfoldedSoak != null) { + return this.unfoldedSoak; + } + result = (function() { + var fst, i, ifn, prop, ref, snd, _i, _len, _ref2; + if (ifn = _this.base.unfoldSoak(o)) { + Array.prototype.push.apply(ifn.body.properties, _this.properties); + return ifn; + } + _ref2 = _this.properties; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + prop = _ref2[i]; + if (!prop.soak) { + continue; + } + prop.soak = false; + fst = new Value(_this.base, _this.properties.slice(0, i)); + snd = new Value(_this.base, _this.properties.slice(i)); + if (fst.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, fst)); + snd.base = ref; + } + return new If(new Existence(fst), snd, { + soak: true + }); + } + return null; + })(); + return this.unfoldedSoak = result || false; + }; + + return Value; + + })(Base); + + exports.Comment = Comment = (function(_super) { + + __extends(Comment, _super); + + function Comment(comment) { + this.comment = comment; + } + + Comment.prototype.isStatement = YES; + + Comment.prototype.makeReturn = THIS; + + Comment.prototype.compileNode = function(o, level) { + var code; + code = '/*' + multident(this.comment, this.tab) + ("\n" + this.tab + "*/\n"); + if ((level || o.level) === LEVEL_TOP) { + code = o.indent + code; + } + return code; + }; + + return Comment; + + })(Base); + + exports.Call = Call = (function(_super) { + + __extends(Call, _super); + + function Call(variable, args, soak) { + this.args = args != null ? args : []; + this.soak = soak; + this.isNew = false; + this.isSuper = variable === 'super'; + this.variable = this.isSuper ? null : variable; + } + + Call.prototype.children = ['variable', 'args']; + + Call.prototype.newInstance = function() { + var base, _ref2; + base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable; + if (base instanceof Call && !base.isNew) { + base.newInstance(); + } else { + this.isNew = true; + } + return this; + }; + + Call.prototype.superReference = function(o) { + var accesses, method, name; + method = o.scope.namedMethod(); + if (!method) { + throw SyntaxError('cannot call super outside of a function.'); + } + name = method.name; + if (name == null) { + throw SyntaxError('cannot call super on an anonymous function.'); + } + if (method.klass) { + accesses = [new Access(new Literal('__super__'))]; + if (method["static"]) { + accesses.push(new Access(new Literal('constructor'))); + } + accesses.push(new Access(new Literal(name))); + return (new Value(new Literal(method.klass), accesses)).compile(o); + } else { + return "" + name + ".__super__.constructor"; + } + }; + + Call.prototype.superThis = function(o) { + var method; + method = o.scope.method; + return (method && !method.klass && method.context) || "this"; + }; + + Call.prototype.unfoldSoak = function(o) { + var call, ifn, left, list, rite, _i, _len, _ref2, _ref3; + if (this.soak) { + if (this.variable) { + if (ifn = unfoldSoak(o, this, 'variable')) { + return ifn; + } + _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; + } else { + left = new Literal(this.superReference(o)); + rite = new Value(left); + } + rite = new Call(rite, this.args); + rite.isNew = this.isNew; + left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); + return new If(left, new Value(rite), { + soak: true + }); + } + call = this; + list = []; + while (true) { + if (call.variable instanceof Call) { + list.push(call); + call = call.variable; + continue; + } + if (!(call.variable instanceof Value)) { + break; + } + list.push(call); + if (!((call = call.variable.base) instanceof Call)) { + break; + } + } + _ref3 = list.reverse(); + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + call = _ref3[_i]; + if (ifn) { + if (call.variable instanceof Call) { + call.variable = ifn; + } else { + call.variable.base = ifn; + } + } + ifn = unfoldSoak(o, call, 'variable'); + } + return ifn; + }; + + Call.prototype.filterImplicitObjects = function(list) { + var node, nodes, obj, prop, properties, _i, _j, _len, _len1, _ref2; + nodes = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + node = list[_i]; + if (!((typeof node.isObject === "function" ? node.isObject() : void 0) && node.base.generated)) { + nodes.push(node); + continue; + } + obj = null; + _ref2 = node.base.properties; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + prop = _ref2[_j]; + if (prop instanceof Assign || prop instanceof Comment) { + if (!obj) { + nodes.push(obj = new Obj(properties = [], true)); + } + properties.push(prop); + } else { + nodes.push(prop); + obj = null; + } + } + } + return nodes; + }; + + Call.prototype.compileNode = function(o) { + var arg, args, code, _ref2; + if ((_ref2 = this.variable) != null) { + _ref2.front = this.front; + } + if (code = Splat.compileSplattedArray(o, this.args, true)) { + return this.compileSplat(o, code); + } + args = this.filterImplicitObjects(this.args); + args = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + _results.push(arg.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (this.isSuper) { + return this.superReference(o) + (".call(" + (this.superThis(o)) + (args && ', ' + args) + ")"); + } else { + return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")"); + } + }; + + Call.prototype.compileSuper = function(args, o) { + return "" + (this.superReference(o)) + ".call(" + (this.superThis(o)) + (args.length ? ', ' : '') + args + ")"; + }; + + Call.prototype.compileSplat = function(o, splatArgs) { + var base, fun, idt, name, ref; + if (this.isSuper) { + return "" + (this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", " + splatArgs + ")"; + } + if (this.isNew) { + idt = this.tab + TAB; + return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return Object(result) === result ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function(){})"; + } + base = new Value(this.variable); + if ((name = base.properties.pop()) && base.isComplex()) { + ref = o.scope.freeVariable('ref'); + fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o)); + } else { + fun = base.compile(o, LEVEL_ACCESS); + if (SIMPLENUM.test(fun)) { + fun = "(" + fun + ")"; + } + if (name) { + ref = fun; + fun += name.compile(o); + } else { + ref = 'null'; + } + } + return "" + fun + ".apply(" + ref + ", " + splatArgs + ")"; + }; + + return Call; + + })(Base); + + exports.Extends = Extends = (function(_super) { + + __extends(Extends, _super); + + function Extends(child, parent) { + this.child = child; + this.parent = parent; + } + + Extends.prototype.children = ['child', 'parent']; + + Extends.prototype.compile = function(o) { + return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o); + }; + + return Extends; + + })(Base); + + exports.Access = Access = (function(_super) { + + __extends(Access, _super); + + function Access(name, tag) { + this.name = name; + this.name.asKey = true; + this.soak = tag === 'soak'; + } + + Access.prototype.children = ['name']; + + Access.prototype.compile = function(o) { + var name; + name = this.name.compile(o); + if (IDENTIFIER.test(name)) { + return "." + name; + } else { + return "[" + name + "]"; + } + }; + + Access.prototype.isComplex = NO; + + return Access; + + })(Base); + + exports.Index = Index = (function(_super) { + + __extends(Index, _super); + + function Index(index) { + this.index = index; + } + + Index.prototype.children = ['index']; + + Index.prototype.compile = function(o) { + return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]"; + }; + + Index.prototype.isComplex = function() { + return this.index.isComplex(); + }; + + return Index; + + })(Base); + + exports.Range = Range = (function(_super) { + + __extends(Range, _super); + + Range.prototype.children = ['from', 'to']; + + function Range(from, to, tag) { + this.from = from; + this.to = to; + this.exclusive = tag === 'exclusive'; + this.equals = this.exclusive ? '' : '='; + } + + Range.prototype.compileVariables = function(o) { + var step, _ref2, _ref3, _ref4, _ref5; + o = merge(o, { + top: true + }); + _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1]; + _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1]; + if (step = del(o, 'step')) { + _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1]; + } + _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1]; + if (this.stepVar) { + return this.stepNum = this.stepVar.match(SIMPLENUM); + } + }; + + Range.prototype.compileNode = function(o) { + var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3; + if (!this.fromVar) { + this.compileVariables(o); + } + if (!o.index) { + return this.compileArray(o); + } + known = this.fromNum && this.toNum; + idx = del(o, 'index'); + idxName = del(o, 'name'); + namedIndex = idxName && idxName !== idx; + varPart = "" + idx + " = " + this.fromC; + if (this.toC !== this.toVar) { + varPart += ", " + this.toC; + } + if (this.step !== this.stepVar) { + varPart += ", " + this.step; + } + _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1]; + condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); + stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--"; + if (namedIndex) { + varPart = "" + idxName + " = " + varPart; + } + if (namedIndex) { + stepPart = "" + idxName + " = " + stepPart; + } + return "" + varPart + "; " + condPart + "; " + stepPart; + }; + + Range.prototype.compileArray = function(o) { + var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results; + if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) { + range = (function() { + _results = []; + for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + if (this.exclusive) { + range.pop(); + } + return "[" + (range.join(', ')) + "]"; + } + idt = this.tab + TAB; + i = o.scope.freeVariable('i'); + result = o.scope.freeVariable('results'); + pre = "\n" + idt + result + " = [];"; + if (this.fromNum && this.toNum) { + o.index = i; + body = this.compileNode(o); + } else { + vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : ''); + cond = "" + this.fromVar + " <= " + this.toVar; + body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--"; + } + post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent; + hasArgs = function(node) { + return node != null ? node.contains(function(n) { + return n instanceof Literal && n.value === 'arguments' && !n.asKey; + }) : void 0; + }; + if (hasArgs(this.from) || hasArgs(this.to)) { + args = ', arguments'; + } + return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")"; + }; + + return Range; + + })(Base); + + exports.Slice = Slice = (function(_super) { + + __extends(Slice, _super); + + Slice.prototype.children = ['range']; + + function Slice(range) { + this.range = range; + Slice.__super__.constructor.call(this); + } + + Slice.prototype.compileNode = function(o) { + var compiled, from, fromStr, to, toStr, _ref2; + _ref2 = this.range, to = _ref2.to, from = _ref2.from; + fromStr = from && from.compile(o, LEVEL_PAREN) || '0'; + compiled = to && to.compile(o, LEVEL_PAREN); + if (to && !(!this.range.exclusive && +compiled === -1)) { + toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? "" + (+compiled + 1) : (compiled = to.compile(o, LEVEL_ACCESS), "+" + compiled + " + 1 || 9e9")); + } + return ".slice(" + fromStr + (toStr || '') + ")"; + }; + + return Slice; + + })(Base); + + exports.Obj = Obj = (function(_super) { + + __extends(Obj, _super); + + function Obj(props, generated) { + this.generated = generated != null ? generated : false; + this.objects = this.properties = props || []; + } + + Obj.prototype.children = ['properties']; + + Obj.prototype.compileNode = function(o) { + var i, idt, indent, join, lastNoncom, node, obj, prop, props, _i, _len; + props = this.properties; + if (!props.length) { + return (this.front ? '({})' : '{}'); + } + if (this.generated) { + for (_i = 0, _len = props.length; _i < _len; _i++) { + node = props[_i]; + if (node instanceof Value) { + throw new Error('cannot have an implicit value in an implicit object'); + } + } + } + idt = o.indent += TAB; + lastNoncom = this.lastNonComment(this.properties); + props = (function() { + var _j, _len1, _results; + _results = []; + for (i = _j = 0, _len1 = props.length; _j < _len1; i = ++_j) { + prop = props[i]; + join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; + indent = prop instanceof Comment ? '' : idt; + if (prop instanceof Value && prop["this"]) { + prop = new Assign(prop.properties[0].name, prop, 'object'); + } + if (!(prop instanceof Comment)) { + if (!(prop instanceof Assign)) { + prop = new Assign(prop, prop, 'object'); + } + (prop.variable.base || prop.variable).asKey = true; + } + _results.push(indent + prop.compile(o, LEVEL_TOP) + join); + } + return _results; + })(); + props = props.join(''); + obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}"; + if (this.front) { + return "(" + obj + ")"; + } else { + return obj; + } + }; + + Obj.prototype.assigns = function(name) { + var prop, _i, _len, _ref2; + _ref2 = this.properties; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + prop = _ref2[_i]; + if (prop.assigns(name)) { + return true; + } + } + return false; + }; + + return Obj; + + })(Base); + + exports.Arr = Arr = (function(_super) { + + __extends(Arr, _super); + + function Arr(objs) { + this.objects = objs || []; + } + + Arr.prototype.children = ['objects']; + + Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects; + + Arr.prototype.compileNode = function(o) { + var code, obj, objs; + if (!this.objects.length) { + return '[]'; + } + o.indent += TAB; + objs = this.filterImplicitObjects(this.objects); + if (code = Splat.compileSplattedArray(o, objs)) { + return code; + } + code = ((function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = objs.length; _i < _len; _i++) { + obj = objs[_i]; + _results.push(obj.compile(o, LEVEL_LIST)); + } + return _results; + })()).join(', '); + if (code.indexOf('\n') >= 0) { + return "[\n" + o.indent + code + "\n" + this.tab + "]"; + } else { + return "[" + code + "]"; + } + }; + + Arr.prototype.assigns = function(name) { + var obj, _i, _len, _ref2; + _ref2 = this.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj.assigns(name)) { + return true; + } + } + return false; + }; + + return Arr; + + })(Base); + + exports.Class = Class = (function(_super) { + + __extends(Class, _super); + + function Class(variable, parent, body) { + this.variable = variable; + this.parent = parent; + this.body = body != null ? body : new Block; + this.boundFuncs = []; + this.body.classBody = true; + } + + Class.prototype.children = ['variable', 'parent', 'body']; + + Class.prototype.determineName = function() { + var decl, tail; + if (!this.variable) { + return null; + } + decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value; + if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) { + throw SyntaxError("variable name may not be " + decl); + } + return decl && (decl = IDENTIFIER.test(decl) && decl); + }; + + Class.prototype.setContext = function(name) { + return this.body.traverseChildren(false, function(node) { + if (node.classBody) { + return false; + } + if (node instanceof Literal && node.value === 'this') { + return node.value = name; + } else if (node instanceof Code) { + node.klass = name; + if (node.bound) { + return node.context = name; + } + } + }); + }; + + Class.prototype.addBoundFunctions = function(o) { + var bvar, lhs, _i, _len, _ref2, _results; + if (this.boundFuncs.length) { + _ref2 = this.boundFuncs; + _results = []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + bvar = _ref2[_i]; + lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o); + _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"))); + } + return _results; + } + }; + + Class.prototype.addProperties = function(node, name, o) { + var assign, base, exprs, func, props; + props = node.base.properties.slice(0); + exprs = (function() { + var _results; + _results = []; + while (assign = props.shift()) { + if (assign instanceof Assign) { + base = assign.variable.base; + delete assign.context; + func = assign.value; + if (base.value === 'constructor') { + if (this.ctor) { + throw new Error('cannot define more than one constructor in a class'); + } + if (func.bound) { + throw new Error('cannot define a constructor as a bound function'); + } + if (func instanceof Code) { + assign = this.ctor = func; + } else { + this.externalCtor = o.scope.freeVariable('class'); + assign = new Assign(new Literal(this.externalCtor), func); + } + } else { + if (assign.variable["this"]) { + func["static"] = true; + if (func.bound) { + func.context = name; + } + } else { + assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); + if (func instanceof Code && func.bound) { + this.boundFuncs.push(base); + func.bound = false; + } + } + } + } + _results.push(assign); + } + return _results; + }).call(this); + return compact(exprs); + }; + + Class.prototype.walkBody = function(name, o) { + var _this = this; + return this.traverseChildren(false, function(child) { + var exps, i, node, _i, _len, _ref2; + if (child instanceof Class) { + return false; + } + if (child instanceof Block) { + _ref2 = exps = child.expressions; + for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { + node = _ref2[i]; + if (node instanceof Value && node.isObject(true)) { + exps[i] = _this.addProperties(node, name, o); + } + } + return child.expressions = exps = flatten(exps); + } + }); + }; + + Class.prototype.hoistDirectivePrologue = function() { + var expressions, index, node; + index = 0; + expressions = this.body.expressions; + while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) { + ++index; + } + return this.directives = expressions.splice(0, index); + }; + + Class.prototype.ensureConstructor = function(name) { + if (!this.ctor) { + this.ctor = new Code; + if (this.parent) { + this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)")); + } + if (this.externalCtor) { + this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)")); + } + this.ctor.body.makeReturn(); + this.body.expressions.unshift(this.ctor); + } + this.ctor.ctor = this.ctor.name = name; + this.ctor.klass = null; + return this.ctor.noReturn = true; + }; + + Class.prototype.compileNode = function(o) { + var call, decl, klass, lname, name, params, _ref2; + decl = this.determineName(); + name = decl || '_Class'; + if (name.reserved) { + name = "_" + name; + } + lname = new Literal(name); + this.hoistDirectivePrologue(); + this.setContext(name); + this.walkBody(name, o); + this.ensureConstructor(name); + this.body.spaced = true; + if (!(this.ctor instanceof Code)) { + this.body.expressions.unshift(this.ctor); + } + this.body.expressions.push(lname); + (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives); + this.addBoundFunctions(o); + call = Closure.wrap(this.body); + if (this.parent) { + this.superClass = new Literal(o.scope.freeVariable('super', false)); + this.body.expressions.unshift(new Extends(lname, this.superClass)); + call.args.push(this.parent); + params = call.variable.params || call.variable.base.params; + params.push(new Param(this.superClass)); + } + klass = new Parens(call, true); + if (this.variable) { + klass = new Assign(this.variable, klass); + } + return klass.compile(o); + }; + + return Class; + + })(Base); + + exports.Assign = Assign = (function(_super) { + + __extends(Assign, _super); + + function Assign(variable, value, context, options) { + var forbidden, name, _ref2; + this.variable = variable; + this.value = value; + this.context = context; + this.param = options && options.param; + this.subpattern = options && options.subpattern; + forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0); + if (forbidden && this.context !== 'object') { + throw SyntaxError("variable name may not be \"" + name + "\""); + } + } + + Assign.prototype.children = ['variable', 'value']; + + Assign.prototype.isStatement = function(o) { + return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0; + }; + + Assign.prototype.assigns = function(name) { + return this[this.context === 'object' ? 'value' : 'variable'].assigns(name); + }; + + Assign.prototype.unfoldSoak = function(o) { + return unfoldSoak(o, this, 'variable'); + }; + + Assign.prototype.compileNode = function(o) { + var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5; + if (isValue = this.variable instanceof Value) { + if (this.variable.isArray() || this.variable.isObject()) { + return this.compilePatternMatch(o); + } + if (this.variable.isSplice()) { + return this.compileSplice(o); + } + if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') { + return this.compileConditional(o); + } + } + name = this.variable.compile(o, LEVEL_LIST); + if (!this.context) { + if (!(varBase = this.variable.unwrapAll()).isAssignable()) { + throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned."); + } + if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) { + if (this.param) { + o.scope.add(name, 'var'); + } else { + o.scope.find(name); + } + } + } + if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) { + if (match[1]) { + this.value.klass = match[1]; + } + this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5]; + } + val = this.value.compile(o, LEVEL_LIST); + if (this.context === 'object') { + return "" + name + ": " + val; + } + val = name + (" " + (this.context || '=') + " ") + val; + if (o.level <= LEVEL_LIST) { + return val; + } else { + return "(" + val + ")"; + } + }; + + Assign.prototype.compilePatternMatch = function(o) { + var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + top = o.level === LEVEL_TOP; + value = this.value; + objects = this.variable.base.objects; + if (!(olen = objects.length)) { + code = value.compile(o); + if (o.level >= LEVEL_OP) { + return "(" + code + ")"; + } else { + return code; + } + } + isObject = this.variable.isObject(); + if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) { + if (obj instanceof Assign) { + _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value; + } else { + if (obj.base instanceof Parens) { + _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1]; + } else { + idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); + } + } + acc = IDENTIFIER.test(idx.unwrap().value || 0); + value = new Value(value); + value.properties.push(new (acc ? Access : Index)(idx)); + if (_ref5 = obj.unwrap().value, __indexOf.call(RESERVED, _ref5) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o))); + } + return new Assign(obj, value, null, { + param: this.param + }).compile(o, LEVEL_TOP); + } + vvar = value.compile(o, LEVEL_LIST); + assigns = []; + splat = false; + if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) { + assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar); + vvar = ref; + } + for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) { + obj = objects[i]; + idx = i; + if (isObject) { + if (obj instanceof Assign) { + _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value; + } else { + if (obj.base instanceof Parens) { + _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1]; + } else { + idx = obj["this"] ? obj.properties[0].name : obj; + } + } + } + if (!splat && obj instanceof Splat) { + name = obj.name.unwrap().value; + obj = obj.unwrap(); + val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i; + if (rest = olen - i - 1) { + ivar = o.scope.freeVariable('i'); + val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])"; + } else { + val += ") : []"; + } + val = new Literal(val); + splat = "" + ivar + "++"; + } else { + name = obj.unwrap().value; + if (obj instanceof Splat) { + obj = obj.name.compile(o); + throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "..."); + } + if (typeof idx === 'number') { + idx = new Literal(splat || idx); + acc = false; + } else { + acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0); + } + val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]); + } + if ((name != null) && __indexOf.call(RESERVED, name) >= 0) { + throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o))); + } + assigns.push(new Assign(obj, val, null, { + param: this.param, + subpattern: true + }).compile(o, LEVEL_LIST)); + } + if (!(top || this.subpattern)) { + assigns.push(vvar); + } + code = assigns.join(', '); + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Assign.prototype.compileConditional = function(o) { + var left, right, _ref2; + _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1]; + if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) { + throw new Error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been defined."); + } + if (__indexOf.call(this.context, "?") >= 0) { + o.isExistentialEquals = true; + } + return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o); + }; + + Assign.prototype.compileSplice = function(o) { + var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4; + _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive; + name = this.variable.compile(o); + _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1]; + if (to) { + if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) { + to = +to.compile(o) - +fromRef; + if (!exclusive) { + to += 1; + } + } else { + to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef; + if (!exclusive) { + to += ' + 1'; + } + } + } else { + to = "9e9"; + } + _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1]; + code = "[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat(" + valDef + ")), " + valRef; + if (o.level > LEVEL_TOP) { + return "(" + code + ")"; + } else { + return code; + } + }; + + return Assign; + + })(Base); + + exports.Code = Code = (function(_super) { + + __extends(Code, _super); + + function Code(params, body, tag) { + this.params = params || []; + this.body = body || new Block; + this.bound = tag === 'boundfunc'; + if (this.bound) { + this.context = '_this'; + } + } + + Code.prototype.children = ['params', 'body']; + + Code.prototype.isStatement = function() { + return !!this.ctor; + }; + + Code.prototype.jumps = NO; + + Code.prototype.compileNode = function(o) { + var code, exprs, i, idt, lit, name, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + o.scope = new Scope(o.scope, this.body, this); + o.scope.shared = del(o, 'sharedScope'); + o.indent += TAB; + delete o.bare; + delete o.isExistentialEquals; + params = []; + exprs = []; + _ref2 = this.paramNames(); + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + name = _ref2[_i]; + if (!o.scope.check(name)) { + o.scope.parameter(name); + } + } + _ref3 = this.params; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + param = _ref3[_j]; + if (!param.splat) { + continue; + } + _ref4 = this.params; + for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) { + p = _ref4[_k].name; + if (p["this"]) { + p = p.properties[0].name; + } + if (p.value) { + o.scope.add(p.value, 'var', true); + } + } + splats = new Assign(new Value(new Arr((function() { + var _l, _len3, _ref5, _results; + _ref5 = this.params; + _results = []; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + p = _ref5[_l]; + _results.push(p.asReference(o)); + } + return _results; + }).call(this))), new Value(new Literal('arguments'))); + break; + } + _ref5 = this.params; + for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) { + param = _ref5[_l]; + if (param.isComplex()) { + val = ref = param.asReference(o); + if (param.value) { + val = new Op('?', ref, param.value); + } + exprs.push(new Assign(new Value(param.name), val, '=', { + param: true + })); + } else { + ref = param; + if (param.value) { + lit = new Literal(ref.name.value + ' == null'); + val = new Assign(new Value(param.name), param.value, '='); + exprs.push(new If(lit, val)); + } + } + if (!splats) { + params.push(ref); + } + } + wasEmpty = this.body.isEmpty(); + if (splats) { + exprs.unshift(splats); + } + if (exprs.length) { + (_ref6 = this.body.expressions).unshift.apply(_ref6, exprs); + } + for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) { + p = params[i]; + o.scope.parameter(params[i] = p.compile(o)); + } + uniqs = []; + _ref7 = this.paramNames(); + for (_n = 0, _len5 = _ref7.length; _n < _len5; _n++) { + name = _ref7[_n]; + if (__indexOf.call(uniqs, name) >= 0) { + throw SyntaxError("multiple parameters named '" + name + "'"); + } + uniqs.push(name); + } + if (!(wasEmpty || this.noReturn)) { + this.body.makeReturn(); + } + if (this.bound) { + if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) { + this.bound = this.context = o.scope.parent.method.context; + } else if (!this["static"]) { + o.scope.parent.assign('_this', 'this'); + } + } + idt = o.indent; + code = 'function'; + if (this.ctor) { + code += ' ' + this.name; + } + code += '(' + params.join(', ') + ') {'; + if (!this.body.isEmpty()) { + code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab; + } + code += '}'; + if (this.ctor) { + return this.tab + code; + } + if (this.front || (o.level >= LEVEL_ACCESS)) { + return "(" + code + ")"; + } else { + return code; + } + }; + + Code.prototype.paramNames = function() { + var names, param, _i, _len, _ref2; + names = []; + _ref2 = this.params; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + names.push.apply(names, param.names()); + } + return names; + }; + + Code.prototype.traverseChildren = function(crossScope, func) { + if (crossScope) { + return Code.__super__.traverseChildren.call(this, crossScope, func); + } + }; + + return Code; + + })(Base); + + exports.Param = Param = (function(_super) { + + __extends(Param, _super); + + function Param(name, value, splat) { + var _ref2; + this.name = name; + this.value = value; + this.splat = splat; + if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("parameter name \"" + name + "\" is not allowed"); + } + } + + Param.prototype.children = ['name', 'value']; + + Param.prototype.compile = function(o) { + return this.name.compile(o, LEVEL_LIST); + }; + + Param.prototype.asReference = function(o) { + var node; + if (this.reference) { + return this.reference; + } + node = this.name; + if (node["this"]) { + node = node.properties[0].name; + if (node.value.reserved) { + node = new Literal(o.scope.freeVariable(node.value)); + } + } else if (node.isComplex()) { + node = new Literal(o.scope.freeVariable('arg')); + } + node = new Value(node); + if (this.splat) { + node = new Splat(node); + } + return this.reference = node; + }; + + Param.prototype.isComplex = function() { + return this.name.isComplex(); + }; + + Param.prototype.names = function(name) { + var atParam, names, obj, _i, _len, _ref2; + if (name == null) { + name = this.name; + } + atParam = function(obj) { + var value; + value = obj.properties[0].name.value; + if (value.reserved) { + return []; + } else { + return [value]; + } + }; + if (name instanceof Literal) { + return [name.value]; + } + if (name instanceof Value) { + return atParam(name); + } + names = []; + _ref2 = name.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (obj instanceof Assign) { + names.push(obj.value.unwrap().value); + } else if (obj instanceof Splat) { + names.push(obj.name.unwrap().value); + } else if (obj instanceof Value) { + if (obj.isArray() || obj.isObject()) { + names.push.apply(names, this.names(obj.base)); + } else if (obj["this"]) { + names.push.apply(names, atParam(obj)); + } else { + names.push(obj.base.value); + } + } else { + throw SyntaxError("illegal parameter " + (obj.compile())); + } + } + return names; + }; + + return Param; + + })(Base); + + exports.Splat = Splat = (function(_super) { + + __extends(Splat, _super); + + Splat.prototype.children = ['name']; + + Splat.prototype.isAssignable = YES; + + function Splat(name) { + this.name = name.compile ? name : new Literal(name); + } + + Splat.prototype.assigns = function(name) { + return this.name.assigns(name); + }; + + Splat.prototype.compile = function(o) { + if (this.index != null) { + return this.compileParam(o); + } else { + return this.name.compile(o); + } + }; + + Splat.prototype.unwrap = function() { + return this.name; + }; + + Splat.compileSplattedArray = function(o, list, apply) { + var args, base, code, i, index, node, _i, _len; + index = -1; + while ((node = list[++index]) && !(node instanceof Splat)) { + continue; + } + if (index >= list.length) { + return ''; + } + if (list.length === 1) { + code = list[0].compile(o, LEVEL_LIST); + if (apply) { + return code; + } + return "" + (utility('slice')) + ".call(" + code + ")"; + } + args = list.slice(index); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + node = args[i]; + code = node.compile(o, LEVEL_LIST); + args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]"; + } + if (index === 0) { + return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")"); + } + base = (function() { + var _j, _len1, _ref2, _results; + _ref2 = list.slice(0, index); + _results = []; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + node = _ref2[_j]; + _results.push(node.compile(o, LEVEL_LIST)); + } + return _results; + })(); + return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")"; + }; + + return Splat; + + })(Base); + + exports.While = While = (function(_super) { + + __extends(While, _super); + + function While(condition, options) { + this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition; + this.guard = options != null ? options.guard : void 0; + } + + While.prototype.children = ['condition', 'guard', 'body']; + + While.prototype.isStatement = YES; + + While.prototype.makeReturn = function(res) { + if (res) { + return While.__super__.makeReturn.apply(this, arguments); + } else { + this.returns = !this.jumps({ + loop: true + }); + return this; + } + }; + + While.prototype.addBody = function(body) { + this.body = body; + return this; + }; + + While.prototype.jumps = function() { + var expressions, node, _i, _len; + expressions = this.body.expressions; + if (!expressions.length) { + return false; + } + for (_i = 0, _len = expressions.length; _i < _len; _i++) { + node = expressions[_i]; + if (node.jumps({ + loop: true + })) { + return node; + } + } + return false; + }; + + While.prototype.compileNode = function(o) { + var body, code, rvar, set; + o.indent += TAB; + set = ''; + body = this.body; + if (body.isEmpty()) { + body = ''; + } else { + if (this.returns) { + body.makeReturn(rvar = o.scope.freeVariable('results')); + set = "" + this.tab + rvar + " = [];\n"; + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) { + body = Block.wrap([new If(this.guard, body)]); + } + } + } + body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab; + } + code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}"); + if (this.returns) { + code += "\n" + this.tab + "return " + rvar + ";"; + } + return code; + }; + + return While; + + })(Base); + + exports.Op = Op = (function(_super) { + var CONVERSIONS, INVERSIONS; + + __extends(Op, _super); + + function Op(op, first, second, flip) { + if (op === 'in') { + return new In(first, second); + } + if (op === 'do') { + return this.generateDo(first); + } + if (op === 'new') { + if (first instanceof Call && !first["do"] && !first.isNew) { + return first.newInstance(); + } + if (first instanceof Code && first.bound || first["do"]) { + first = new Parens(first); + } + } + this.operator = CONVERSIONS[op] || op; + this.first = first; + this.second = second; + this.flip = !!flip; + return this; + } + + CONVERSIONS = { + '==': '===', + '!=': '!==', + 'of': 'in' + }; + + INVERSIONS = { + '!==': '===', + '===': '!==' + }; + + Op.prototype.children = ['first', 'second']; + + Op.prototype.isSimpleNumber = NO; + + Op.prototype.isUnary = function() { + return !this.second; + }; + + Op.prototype.isComplex = function() { + var _ref2; + return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex(); + }; + + Op.prototype.isChainable = function() { + var _ref2; + return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!=='; + }; + + Op.prototype.invert = function() { + var allInvertable, curr, fst, op, _ref2; + if (this.isChainable() && this.first.isChainable()) { + allInvertable = true; + curr = this; + while (curr && curr.operator) { + allInvertable && (allInvertable = curr.operator in INVERSIONS); + curr = curr.first; + } + if (!allInvertable) { + return new Parens(this).invert(); + } + curr = this; + while (curr && curr.operator) { + curr.invert = !curr.invert; + curr.operator = INVERSIONS[curr.operator]; + curr = curr.first; + } + return this; + } else if (op = INVERSIONS[this.operator]) { + this.operator = op; + if (this.first.unwrap() instanceof Op) { + this.first.invert(); + } + return this; + } else if (this.second) { + return new Parens(this).invert(); + } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) { + return fst; + } else { + return new Op('!', this); + } + }; + + Op.prototype.unfoldSoak = function(o) { + var _ref2; + return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first'); + }; + + Op.prototype.generateDo = function(exp) { + var call, func, param, passedParams, ref, _i, _len, _ref2; + passedParams = []; + func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; + _ref2 = func.params || []; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + param = _ref2[_i]; + if (param.value) { + passedParams.push(param.value); + delete param.value; + } else { + passedParams.push(param); + } + } + call = new Call(exp, passedParams); + call["do"] = true; + return call; + }; + + Op.prototype.compileNode = function(o) { + var code, isChain, _ref2, _ref3; + isChain = this.isChainable() && this.first.isChainable(); + if (!isChain) { + this.first.front = this.front; + } + if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) { + throw SyntaxError('delete operand may not be argument or var'); + } + if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) { + throw SyntaxError('prefix increment/decrement may not have eval or arguments operand'); + } + if (this.isUnary()) { + return this.compileUnary(o); + } + if (isChain) { + return this.compileChain(o); + } + if (this.operator === '?') { + return this.compileExistence(o); + } + code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP); + if (o.level <= LEVEL_OP) { + return code; + } else { + return "(" + code + ")"; + } + }; + + Op.prototype.compileChain = function(o) { + var code, fst, shared, _ref2; + _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1]; + fst = this.first.compile(o, LEVEL_OP); + code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP)); + return "(" + code + ")"; + }; + + Op.prototype.compileExistence = function(o) { + var fst, ref; + if (this.first.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, this.first)); + } else { + fst = this.first; + ref = fst; + } + return new If(new Existence(fst), ref, { + type: 'if' + }).addElse(this.second).compile(o); + }; + + Op.prototype.compileUnary = function(o) { + var op, parts, plusMinus; + if (o.level >= LEVEL_ACCESS) { + return (new Parens(this)).compile(o); + } + parts = [op = this.operator]; + plusMinus = op === '+' || op === '-'; + if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) { + parts.push(' '); + } + if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) { + this.first = new Parens(this.first); + } + parts.push(this.first.compile(o, LEVEL_OP)); + if (this.flip) { + parts.reverse(); + } + return parts.join(''); + }; + + Op.prototype.toString = function(idt) { + return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); + }; + + return Op; + + })(Base); + + exports.In = In = (function(_super) { + + __extends(In, _super); + + function In(object, array) { + this.object = object; + this.array = array; + } + + In.prototype.children = ['object', 'array']; + + In.prototype.invert = NEGATE; + + In.prototype.compileNode = function(o) { + var hasSplat, obj, _i, _len, _ref2; + if (this.array instanceof Value && this.array.isArray()) { + _ref2 = this.array.base.objects; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + obj = _ref2[_i]; + if (!(obj instanceof Splat)) { + continue; + } + hasSplat = true; + break; + } + if (!hasSplat) { + return this.compileOrTest(o); + } + } + return this.compileLoopTest(o); + }; + + In.prototype.compileOrTest = function(o) { + var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3; + if (this.array.base.objects.length === 0) { + return "" + (!!this.negated); + } + _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1]; + _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1]; + tests = (function() { + var _i, _len, _ref4, _results; + _ref4 = this.array.base.objects; + _results = []; + for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { + item = _ref4[i]; + _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS)); + } + return _results; + }).call(this); + tests = tests.join(cnj); + if (o.level < LEVEL_OP) { + return tests; + } else { + return "(" + tests + ")"; + } + }; + + In.prototype.compileLoopTest = function(o) { + var code, ref, sub, _ref2; + _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1]; + code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0'); + if (sub === ref) { + return code; + } + code = sub + ', ' + code; + if (o.level < LEVEL_LIST) { + return code; + } else { + return "(" + code + ")"; + } + }; + + In.prototype.toString = function(idt) { + return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : '')); + }; + + return In; + + })(Base); + + exports.Try = Try = (function(_super) { + + __extends(Try, _super); + + function Try(attempt, error, recovery, ensure) { + this.attempt = attempt; + this.error = error; + this.recovery = recovery; + this.ensure = ensure; + } + + Try.prototype.children = ['attempt', 'recovery', 'ensure']; + + Try.prototype.isStatement = YES; + + Try.prototype.jumps = function(o) { + var _ref2; + return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0); + }; + + Try.prototype.makeReturn = function(res) { + if (this.attempt) { + this.attempt = this.attempt.makeReturn(res); + } + if (this.recovery) { + this.recovery = this.recovery.makeReturn(res); + } + return this; + }; + + Try.prototype.compileNode = function(o) { + var catchPart, ensurePart, errorPart, tryPart; + o.indent += TAB; + errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' '; + tryPart = this.attempt.compile(o, LEVEL_TOP); + catchPart = (function() { + var _ref2; + if (this.recovery) { + if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + throw SyntaxError("catch variable may not be \"" + this.error.value + "\""); + } + if (!o.scope.check(this.error.value)) { + o.scope.add(this.error.value, 'param'); + } + return " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"; + } else if (!(this.ensure || this.recovery)) { + return ' catch (_error) {}'; + } + }).call(this); + ensurePart = this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : ''; + return "" + this.tab + "try {\n" + tryPart + "\n" + this.tab + "}" + (catchPart || '') + ensurePart; + }; + + return Try; + + })(Base); + + exports.Throw = Throw = (function(_super) { + + __extends(Throw, _super); + + function Throw(expression) { + this.expression = expression; + } + + Throw.prototype.children = ['expression']; + + Throw.prototype.isStatement = YES; + + Throw.prototype.jumps = NO; + + Throw.prototype.makeReturn = THIS; + + Throw.prototype.compileNode = function(o) { + return this.tab + ("throw " + (this.expression.compile(o)) + ";"); + }; + + return Throw; + + })(Base); + + exports.Existence = Existence = (function(_super) { + + __extends(Existence, _super); + + function Existence(expression) { + this.expression = expression; + } + + Existence.prototype.children = ['expression']; + + Existence.prototype.invert = NEGATE; + + Existence.prototype.compileNode = function(o) { + var cmp, cnj, code, _ref2; + this.expression.front = this.front; + code = this.expression.compile(o, LEVEL_OP); + if (IDENTIFIER.test(code) && !o.scope.check(code)) { + _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1]; + code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null"; + } else { + code = "" + code + " " + (this.negated ? '==' : '!=') + " null"; + } + if (o.level <= LEVEL_COND) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Existence; + + })(Base); + + exports.Parens = Parens = (function(_super) { + + __extends(Parens, _super); + + function Parens(body) { + this.body = body; + } + + Parens.prototype.children = ['body']; + + Parens.prototype.unwrap = function() { + return this.body; + }; + + Parens.prototype.isComplex = function() { + return this.body.isComplex(); + }; + + Parens.prototype.compileNode = function(o) { + var bare, code, expr; + expr = this.body.unwrap(); + if (expr instanceof Value && expr.isAtomic()) { + expr.front = this.front; + return expr.compile(o); + } + code = expr.compile(o, LEVEL_PAREN); + bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns)); + if (bare) { + return code; + } else { + return "(" + code + ")"; + } + }; + + return Parens; + + })(Base); + + exports.For = For = (function(_super) { + + __extends(For, _super); + + function For(body, source) { + var _ref2; + this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; + this.body = Block.wrap([body]); + this.own = !!source.own; + this.object = !!source.object; + if (this.object) { + _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1]; + } + if (this.index instanceof Value) { + throw SyntaxError('index cannot be a pattern matching expression'); + } + this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; + this.pattern = this.name instanceof Value; + if (this.range && this.index) { + throw SyntaxError('indexes do not apply to range loops'); + } + if (this.range && this.pattern) { + throw SyntaxError('cannot pattern match over range loops'); + } + this.returns = false; + } + + For.prototype.children = ['body', 'source', 'guard', 'step']; + + For.prototype.compileNode = function(o) { + var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2; + body = Block.wrap([this.body]); + lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0; + if (lastJumps && lastJumps instanceof Return) { + this.returns = false; + } + source = this.range ? this.source.base : this.source; + scope = o.scope; + name = this.name && this.name.compile(o, LEVEL_LIST); + index = this.index && this.index.compile(o, LEVEL_LIST); + if (name && !this.pattern) { + scope.find(name); + } + if (index) { + scope.find(index); + } + if (this.returns) { + rvar = scope.freeVariable('results'); + } + ivar = (this.object && index) || scope.freeVariable('i'); + kvar = (this.range && name) || index || ivar; + kvarAssign = kvar !== ivar ? "" + kvar + " = " : ""; + if (this.step && !this.range) { + stepvar = scope.freeVariable("step"); + } + if (this.pattern) { + name = ivar; + } + varPart = ''; + guardPart = ''; + defPart = ''; + idt1 = this.tab + TAB; + if (this.range) { + forPart = source.compile(merge(o, { + index: ivar, + name: name, + step: this.step + })); + } else { + svar = this.source.compile(o, LEVEL_LIST); + if ((name || this.own) && !IDENTIFIER.test(svar)) { + defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n"; + svar = ref; + } + if (name && !this.pattern) { + namePart = "" + name + " = " + svar + "[" + kvar + "]"; + } + if (!this.object) { + lvar = scope.freeVariable('len'); + forVarPart = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length"; + if (this.step) { + forVarPart += ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)); + } + stepPart = "" + kvarAssign + (this.step ? "" + ivar + " += " + stepvar : (kvar !== ivar ? "++" + ivar : "" + ivar + "++")); + forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart; + } + } + if (this.returns) { + resultPart = "" + this.tab + rvar + " = [];\n"; + returnResult = "\n" + this.tab + "return " + rvar + ";"; + body.makeReturn(rvar); + } + if (this.guard) { + if (body.expressions.length > 1) { + body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); + } else { + if (this.guard) { + body = Block.wrap([new If(this.guard, body)]); + } + } + } + if (this.pattern) { + body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + kvar + "]"))); + } + defPart += this.pluckDirectCall(o, body); + if (namePart) { + varPart = "\n" + idt1 + namePart + ";"; + } + if (this.object) { + forPart = "" + kvar + " in " + svar; + if (this.own) { + guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + kvar + ")) continue;"; + } + } + body = body.compile(merge(o, { + indent: idt1 + }), LEVEL_TOP); + if (body) { + body = '\n' + body + '\n'; + } + return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || ''); + }; + + For.prototype.pluckDirectCall = function(o, body) { + var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; + defs = ''; + _ref2 = body.expressions; + for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) { + expr = _ref2[idx]; + expr = expr.unwrapAll(); + if (!(expr instanceof Call)) { + continue; + } + val = expr.variable.unwrapAll(); + if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) { + continue; + } + fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val; + ref = new Literal(o.scope.freeVariable('fn')); + base = new Value(ref); + if (val.base) { + _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1]; + } + body.expressions[idx] = new Call(base, expr.args); + defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'; + } + return defs; + }; + + return For; + + })(While); + + exports.Switch = Switch = (function(_super) { + + __extends(Switch, _super); + + function Switch(subject, cases, otherwise) { + this.subject = subject; + this.cases = cases; + this.otherwise = otherwise; + } + + Switch.prototype.children = ['subject', 'cases', 'otherwise']; + + Switch.prototype.isStatement = YES; + + Switch.prototype.jumps = function(o) { + var block, conds, _i, _len, _ref2, _ref3, _ref4; + if (o == null) { + o = { + block: true + }; + } + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1]; + if (block.jumps(o)) { + return block; + } + } + return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0; + }; + + Switch.prototype.makeReturn = function(res) { + var pair, _i, _len, _ref2, _ref3; + _ref2 = this.cases; + for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + pair = _ref2[_i]; + pair[1].makeReturn(res); + } + if (res) { + this.otherwise || (this.otherwise = new Block([new Literal('void 0')])); + } + if ((_ref3 = this.otherwise) != null) { + _ref3.makeReturn(res); + } + return this; + }; + + Switch.prototype.compileNode = function(o) { + var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4, _ref5; + idt1 = o.indent + TAB; + idt2 = o.indent = idt1 + TAB; + code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n"); + _ref3 = this.cases; + for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { + _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1]; + _ref5 = flatten([conditions]); + for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) { + cond = _ref5[_j]; + if (!this.subject) { + cond = cond.invert(); + } + code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n"); + } + if (body = block.compile(o, LEVEL_TOP)) { + code += body + '\n'; + } + if (i === this.cases.length - 1 && !this.otherwise) { + break; + } + expr = this.lastNonComment(block.expressions); + if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) { + continue; + } + code += idt2 + 'break;\n'; + } + if (this.otherwise && this.otherwise.expressions.length) { + code += idt1 + ("default:\n" + (this.otherwise.compile(o, LEVEL_TOP)) + "\n"); + } + return code + this.tab + '}'; + }; + + return Switch; + + })(Base); + + exports.If = If = (function(_super) { + + __extends(If, _super); + + function If(condition, body, options) { + this.body = body; + if (options == null) { + options = {}; + } + this.condition = options.type === 'unless' ? condition.invert() : condition; + this.elseBody = null; + this.isChain = false; + this.soak = options.soak; + } + + If.prototype.children = ['condition', 'body', 'elseBody']; + + If.prototype.bodyNode = function() { + var _ref2; + return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.elseBodyNode = function() { + var _ref2; + return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0; + }; + + If.prototype.addElse = function(elseBody) { + if (this.isChain) { + this.elseBodyNode().addElse(elseBody); + } else { + this.isChain = elseBody instanceof If; + this.elseBody = this.ensureBlock(elseBody); + } + return this; + }; + + If.prototype.isStatement = function(o) { + var _ref2; + return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0); + }; + + If.prototype.jumps = function(o) { + var _ref2; + return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0); + }; + + If.prototype.compileNode = function(o) { + if (this.isStatement(o)) { + return this.compileStatement(o); + } else { + return this.compileExpression(o); + } + }; + + If.prototype.makeReturn = function(res) { + if (res) { + this.elseBody || (this.elseBody = new Block([new Literal('void 0')])); + } + this.body && (this.body = new Block([this.body.makeReturn(res)])); + this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)])); + return this; + }; + + If.prototype.ensureBlock = function(node) { + if (node instanceof Block) { + return node; + } else { + return new Block([node]); + } + }; + + If.prototype.compileStatement = function(o) { + var body, child, cond, exeq, ifPart; + child = del(o, 'chainChild'); + exeq = del(o, 'isExistentialEquals'); + if (exeq) { + return new If(this.condition.invert(), this.elseBodyNode(), { + type: 'if' + }).compile(o); + } + cond = this.condition.compile(o, LEVEL_PAREN); + o.indent += TAB; + body = this.ensureBlock(this.body); + ifPart = "if (" + cond + ") {\n" + (body.compile(o)) + "\n" + this.tab + "}"; + if (!child) { + ifPart = this.tab + ifPart; + } + if (!this.elseBody) { + return ifPart; + } + return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}"); + }; + + If.prototype.compileExpression = function(o) { + var alt, body, code, cond; + cond = this.condition.compile(o, LEVEL_COND); + body = this.bodyNode().compile(o, LEVEL_LIST); + alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0'; + code = "" + cond + " ? " + body + " : " + alt; + if (o.level >= LEVEL_COND) { + return "(" + code + ")"; + } else { + return code; + } + }; + + If.prototype.unfoldSoak = function() { + return this.soak && this; + }; + + return If; + + })(Base); + + Closure = { + wrap: function(expressions, statement, noReturn) { + var args, call, func, mentionsArgs, meth; + if (expressions.jumps()) { + return expressions; + } + func = new Code([], Block.wrap([expressions])); + args = []; + if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) { + meth = new Literal(mentionsArgs ? 'apply' : 'call'); + args = [new Literal('this')]; + if (mentionsArgs) { + args.push(new Literal('arguments')); + } + func = new Value(func, [new Access(meth)]); + } + func.noReturn = noReturn; + call = new Call(func, args); + if (statement) { + return Block.wrap([call]); + } else { + return call; + } + }, + literalArgs: function(node) { + return node instanceof Literal && node.value === 'arguments' && !node.asKey; + }, + literalThis: function(node) { + return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper); + } + }; + + unfoldSoak = function(o, parent, name) { + var ifn; + if (!(ifn = parent[name].unfoldSoak(o))) { + return; + } + parent[name] = ifn.body; + ifn.body = new Value(parent); + return ifn; + }; + + UTILITIES = { + "extends": function() { + return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"; + }, + bind: function() { + return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }'; + }, + indexOf: function() { + return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"; + }, + hasProp: function() { + return '{}.hasOwnProperty'; + }, + slice: function() { + return '[].slice'; + } + }; + + LEVEL_TOP = 1; + + LEVEL_PAREN = 2; + + LEVEL_LIST = 3; + + LEVEL_COND = 4; + + LEVEL_OP = 5; + + LEVEL_ACCESS = 6; + + TAB = ' '; + + IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"; + + IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$"); + + SIMPLENUM = /^[+-]?\d+$/; + + METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$"); + + IS_STRING = /^['"]/; + + utility = function(name) { + var ref; + ref = "__" + name; + Scope.root.assign(ref, UTILITIES[name]()); + return ref; + }; + + multident = function(code, tab) { + code = code.replace(/\n/g, '$&' + tab); + return code.replace(/\s+$/, ''); + }; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/optparse.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/optparse.js new file mode 100644 index 0000000..d9bab41 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/optparse.js @@ -0,0 +1,138 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; + + exports.OptionParser = OptionParser = (function() { + + function OptionParser(rules, banner) { + this.banner = banner; + this.rules = buildRules(rules); + } + + OptionParser.prototype.parse = function(args) { + var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref; + options = { + "arguments": [] + }; + skippingArgument = false; + originalArgs = args; + args = normalizeArguments(args); + for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) { + arg = args[i]; + if (skippingArgument) { + skippingArgument = false; + continue; + } + if (arg === '--') { + pos = originalArgs.indexOf('--'); + options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1)); + break; + } + isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); + seenNonOptionArg = options["arguments"].length > 0; + if (!seenNonOptionArg) { + matchedRule = false; + _ref = this.rules; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + rule = _ref[_j]; + if (rule.shortFlag === arg || rule.longFlag === arg) { + value = true; + if (rule.hasArgument) { + skippingArgument = true; + value = args[i + 1]; + } + options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value; + matchedRule = true; + break; + } + } + if (isOption && !matchedRule) { + throw new Error("unrecognized option: " + arg); + } + } + if (seenNonOptionArg || !isOption) { + options["arguments"].push(arg); + } + } + return options; + }; + + OptionParser.prototype.help = function() { + var letPart, lines, rule, spaces, _i, _len, _ref; + lines = []; + if (this.banner) { + lines.unshift("" + this.banner + "\n"); + } + _ref = this.rules; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + rule = _ref[_i]; + spaces = 15 - rule.longFlag.length; + spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; + letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; + lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); + } + return "\n" + (lines.join('\n')) + "\n"; + }; + + return OptionParser; + + })(); + + LONG_FLAG = /^(--\w[\w\-]*)/; + + SHORT_FLAG = /^(-\w)$/; + + MULTI_FLAG = /^-(\w{2,})/; + + OPTIONAL = /\[(\w+(\*?))\]/; + + buildRules = function(rules) { + var tuple, _i, _len, _results; + _results = []; + for (_i = 0, _len = rules.length; _i < _len; _i++) { + tuple = rules[_i]; + if (tuple.length < 3) { + tuple.unshift(null); + } + _results.push(buildRule.apply(null, tuple)); + } + return _results; + }; + + buildRule = function(shortFlag, longFlag, description, options) { + var match; + if (options == null) { + options = {}; + } + match = longFlag.match(OPTIONAL); + longFlag = longFlag.match(LONG_FLAG)[1]; + return { + name: longFlag.substr(2), + shortFlag: shortFlag, + longFlag: longFlag, + description: description, + hasArgument: !!(match && match[1]), + isList: !!(match && match[2]) + }; + }; + + normalizeArguments = function(args) { + var arg, l, match, result, _i, _j, _len, _len1, _ref; + args = args.slice(0); + result = []; + for (_i = 0, _len = args.length; _i < _len; _i++) { + arg = args[_i]; + if (match = arg.match(MULTI_FLAG)) { + _ref = match[1].split(''); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + l = _ref[_j]; + result.push('-' + l); + } + } else { + result.push(arg); + } + } + return result; + }; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/parser.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/parser.js new file mode 100755 index 0000000..f049903 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/parser.js @@ -0,0 +1,683 @@ +/* Jison generated parser */ +var parser = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Comment":11,"STATEMENT":12,"Value":13,"Invocation":14,"Code":15,"Operation":16,"Assign":17,"If":18,"Try":19,"While":20,"For":21,"Switch":22,"Class":23,"Throw":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"DEBUGGER":35,"UNDEFINED":36,"NULL":37,"BOOL":38,"Assignable":39,"=":40,"AssignObj":41,"ObjAssignable":42,":":43,"ThisProperty":44,"RETURN":45,"HERECOMMENT":46,"PARAM_START":47,"ParamList":48,"PARAM_END":49,"FuncGlyph":50,"->":51,"=>":52,"OptComma":53,",":54,"Param":55,"ParamVar":56,"...":57,"Array":58,"Object":59,"Splat":60,"SimpleAssignable":61,"Accessor":62,"Parenthetical":63,"Range":64,"This":65,".":66,"?.":67,"::":68,"Index":69,"INDEX_START":70,"IndexValue":71,"INDEX_END":72,"INDEX_SOAK":73,"Slice":74,"{":75,"AssignList":76,"}":77,"CLASS":78,"EXTENDS":79,"OptFuncExist":80,"Arguments":81,"SUPER":82,"FUNC_EXIST":83,"CALL_START":84,"CALL_END":85,"ArgList":86,"THIS":87,"@":88,"[":89,"]":90,"RangeDots":91,"..":92,"Arg":93,"SimpleArgs":94,"TRY":95,"Catch":96,"FINALLY":97,"CATCH":98,"THROW":99,"(":100,")":101,"WhileSource":102,"WHILE":103,"WHEN":104,"UNTIL":105,"Loop":106,"LOOP":107,"ForBody":108,"FOR":109,"ForStart":110,"ForSource":111,"ForVariables":112,"OWN":113,"ForValue":114,"FORIN":115,"FOROF":116,"BY":117,"SWITCH":118,"Whens":119,"ELSE":120,"When":121,"LEADING_WHEN":122,"IfBlock":123,"IF":124,"POST_IF":125,"UNARY":126,"-":127,"+":128,"--":129,"++":130,"?":131,"MATH":132,"SHIFT":133,"COMPARE":134,"LOGIC":135,"RELATION":136,"COMPOUND_ASSIGN":137,"$accept":0,"$end":1}, +terminals_: {2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",70:"INDEX_START",72:"INDEX_END",73:"INDEX_SOAK",75:"{",77:"}",78:"CLASS",79:"EXTENDS",82:"SUPER",83:"FUNC_EXIST",84:"CALL_START",85:"CALL_END",87:"THIS",88:"@",89:"[",90:"]",92:"..",95:"TRY",97:"FINALLY",98:"CATCH",99:"THROW",100:"(",101:")",103:"WHILE",104:"WHEN",105:"UNTIL",107:"LOOP",109:"FOR",113:"OWN",115:"FORIN",116:"FOROF",117:"BY",118:"SWITCH",120:"ELSE",122:"LEADING_WHEN",124:"IF",125:"POST_IF",126:"UNARY",127:"-",128:"+",129:"--",130:"++",131:"?",132:"MATH",133:"SHIFT",134:"COMPARE",135:"LOGIC",136:"RELATION",137:"COMPOUND_ASSIGN"}, +productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[10,2],[10,1],[11,1],[15,5],[15,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[13,1],[13,1],[13,1],[13,1],[13,1],[62,2],[62,2],[62,2],[62,1],[62,1],[69,3],[69,2],[71,1],[71,1],[59,4],[76,0],[76,1],[76,3],[76,4],[76,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[80,0],[80,1],[81,2],[81,4],[65,1],[65,1],[44,2],[58,2],[58,4],[91,1],[91,1],[64,5],[74,3],[74,2],[74,2],[74,1],[86,1],[86,3],[86,4],[86,4],[86,6],[93,1],[93,1],[94,1],[94,3],[19,2],[19,3],[19,4],[19,5],[96,3],[24,2],[63,3],[63,5],[102,2],[102,4],[102,2],[102,4],[20,2],[20,2],[20,2],[20,1],[106,2],[106,2],[21,2],[21,2],[21,2],[108,2],[108,2],[110,2],[110,3],[114,1],[114,1],[114,1],[114,1],[112,1],[112,3],[111,2],[111,2],[111,4],[111,4],[111,4],[111,6],[111,6],[22,5],[22,7],[22,4],[22,6],[119,1],[119,2],[121,3],[121,4],[123,3],[123,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1:return this.$ = new yy.Block; +break; +case 2:return this.$ = $$[$0]; +break; +case 3:return this.$ = $$[$0-1]; +break; +case 4:this.$ = yy.Block.wrap([$$[$0]]); +break; +case 5:this.$ = $$[$0-2].push($$[$0]); +break; +case 6:this.$ = $$[$0-1]; +break; +case 7:this.$ = $$[$0]; +break; +case 8:this.$ = $$[$0]; +break; +case 9:this.$ = $$[$0]; +break; +case 10:this.$ = $$[$0]; +break; +case 11:this.$ = new yy.Literal($$[$0]); +break; +case 12:this.$ = $$[$0]; +break; +case 13:this.$ = $$[$0]; +break; +case 14:this.$ = $$[$0]; +break; +case 15:this.$ = $$[$0]; +break; +case 16:this.$ = $$[$0]; +break; +case 17:this.$ = $$[$0]; +break; +case 18:this.$ = $$[$0]; +break; +case 19:this.$ = $$[$0]; +break; +case 20:this.$ = $$[$0]; +break; +case 21:this.$ = $$[$0]; +break; +case 22:this.$ = $$[$0]; +break; +case 23:this.$ = $$[$0]; +break; +case 24:this.$ = new yy.Block; +break; +case 25:this.$ = $$[$0-1]; +break; +case 26:this.$ = new yy.Literal($$[$0]); +break; +case 27:this.$ = new yy.Literal($$[$0]); +break; +case 28:this.$ = new yy.Literal($$[$0]); +break; +case 29:this.$ = $$[$0]; +break; +case 30:this.$ = new yy.Literal($$[$0]); +break; +case 31:this.$ = new yy.Literal($$[$0]); +break; +case 32:this.$ = new yy.Literal($$[$0]); +break; +case 33:this.$ = new yy.Undefined; +break; +case 34:this.$ = new yy.Null; +break; +case 35:this.$ = new yy.Bool($$[$0]); +break; +case 36:this.$ = new yy.Assign($$[$0-2], $$[$0]); +break; +case 37:this.$ = new yy.Assign($$[$0-3], $$[$0]); +break; +case 38:this.$ = new yy.Assign($$[$0-4], $$[$0-1]); +break; +case 39:this.$ = new yy.Value($$[$0]); +break; +case 40:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object'); +break; +case 41:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object'); +break; +case 42:this.$ = $$[$0]; +break; +case 43:this.$ = $$[$0]; +break; +case 44:this.$ = $$[$0]; +break; +case 45:this.$ = $$[$0]; +break; +case 46:this.$ = new yy.Return($$[$0]); +break; +case 47:this.$ = new yy.Return; +break; +case 48:this.$ = new yy.Comment($$[$0]); +break; +case 49:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]); +break; +case 50:this.$ = new yy.Code([], $$[$0], $$[$0-1]); +break; +case 51:this.$ = 'func'; +break; +case 52:this.$ = 'boundfunc'; +break; +case 53:this.$ = $$[$0]; +break; +case 54:this.$ = $$[$0]; +break; +case 55:this.$ = []; +break; +case 56:this.$ = [$$[$0]]; +break; +case 57:this.$ = $$[$0-2].concat($$[$0]); +break; +case 58:this.$ = $$[$0-3].concat($$[$0]); +break; +case 59:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 60:this.$ = new yy.Param($$[$0]); +break; +case 61:this.$ = new yy.Param($$[$0-1], null, true); +break; +case 62:this.$ = new yy.Param($$[$0-2], $$[$0]); +break; +case 63:this.$ = $$[$0]; +break; +case 64:this.$ = $$[$0]; +break; +case 65:this.$ = $$[$0]; +break; +case 66:this.$ = $$[$0]; +break; +case 67:this.$ = new yy.Splat($$[$0-1]); +break; +case 68:this.$ = new yy.Value($$[$0]); +break; +case 69:this.$ = $$[$0-1].add($$[$0]); +break; +case 70:this.$ = new yy.Value($$[$0-1], [].concat($$[$0])); +break; +case 71:this.$ = $$[$0]; +break; +case 72:this.$ = $$[$0]; +break; +case 73:this.$ = new yy.Value($$[$0]); +break; +case 74:this.$ = new yy.Value($$[$0]); +break; +case 75:this.$ = $$[$0]; +break; +case 76:this.$ = new yy.Value($$[$0]); +break; +case 77:this.$ = new yy.Value($$[$0]); +break; +case 78:this.$ = new yy.Value($$[$0]); +break; +case 79:this.$ = $$[$0]; +break; +case 80:this.$ = new yy.Access($$[$0]); +break; +case 81:this.$ = new yy.Access($$[$0], 'soak'); +break; +case 82:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])]; +break; +case 83:this.$ = new yy.Access(new yy.Literal('prototype')); +break; +case 84:this.$ = $$[$0]; +break; +case 85:this.$ = $$[$0-1]; +break; +case 86:this.$ = yy.extend($$[$0], { + soak: true + }); +break; +case 87:this.$ = new yy.Index($$[$0]); +break; +case 88:this.$ = new yy.Slice($$[$0]); +break; +case 89:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated); +break; +case 90:this.$ = []; +break; +case 91:this.$ = [$$[$0]]; +break; +case 92:this.$ = $$[$0-2].concat($$[$0]); +break; +case 93:this.$ = $$[$0-3].concat($$[$0]); +break; +case 94:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 95:this.$ = new yy.Class; +break; +case 96:this.$ = new yy.Class(null, null, $$[$0]); +break; +case 97:this.$ = new yy.Class(null, $$[$0]); +break; +case 98:this.$ = new yy.Class(null, $$[$0-1], $$[$0]); +break; +case 99:this.$ = new yy.Class($$[$0]); +break; +case 100:this.$ = new yy.Class($$[$0-1], null, $$[$0]); +break; +case 101:this.$ = new yy.Class($$[$0-2], $$[$0]); +break; +case 102:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]); +break; +case 103:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 104:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]); +break; +case 105:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]); +break; +case 106:this.$ = new yy.Call('super', $$[$0]); +break; +case 107:this.$ = false; +break; +case 108:this.$ = true; +break; +case 109:this.$ = []; +break; +case 110:this.$ = $$[$0-2]; +break; +case 111:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 112:this.$ = new yy.Value(new yy.Literal('this')); +break; +case 113:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this'); +break; +case 114:this.$ = new yy.Arr([]); +break; +case 115:this.$ = new yy.Arr($$[$0-2]); +break; +case 116:this.$ = 'inclusive'; +break; +case 117:this.$ = 'exclusive'; +break; +case 118:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]); +break; +case 119:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]); +break; +case 120:this.$ = new yy.Range($$[$0-1], null, $$[$0]); +break; +case 121:this.$ = new yy.Range(null, $$[$0], $$[$0-1]); +break; +case 122:this.$ = new yy.Range(null, null, $$[$0]); +break; +case 123:this.$ = [$$[$0]]; +break; +case 124:this.$ = $$[$0-2].concat($$[$0]); +break; +case 125:this.$ = $$[$0-3].concat($$[$0]); +break; +case 126:this.$ = $$[$0-2]; +break; +case 127:this.$ = $$[$0-5].concat($$[$0-2]); +break; +case 128:this.$ = $$[$0]; +break; +case 129:this.$ = $$[$0]; +break; +case 130:this.$ = $$[$0]; +break; +case 131:this.$ = [].concat($$[$0-2], $$[$0]); +break; +case 132:this.$ = new yy.Try($$[$0]); +break; +case 133:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]); +break; +case 134:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]); +break; +case 135:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]); +break; +case 136:this.$ = [$$[$0-1], $$[$0]]; +break; +case 137:this.$ = new yy.Throw($$[$0]); +break; +case 138:this.$ = new yy.Parens($$[$0-1]); +break; +case 139:this.$ = new yy.Parens($$[$0-2]); +break; +case 140:this.$ = new yy.While($$[$0]); +break; +case 141:this.$ = new yy.While($$[$0-2], { + guard: $$[$0] + }); +break; +case 142:this.$ = new yy.While($$[$0], { + invert: true + }); +break; +case 143:this.$ = new yy.While($$[$0-2], { + invert: true, + guard: $$[$0] + }); +break; +case 144:this.$ = $$[$0-1].addBody($$[$0]); +break; +case 145:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 146:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]])); +break; +case 147:this.$ = $$[$0]; +break; +case 148:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]); +break; +case 149:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]])); +break; +case 150:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 151:this.$ = new yy.For($$[$0-1], $$[$0]); +break; +case 152:this.$ = new yy.For($$[$0], $$[$0-1]); +break; +case 153:this.$ = { + source: new yy.Value($$[$0]) + }; +break; +case 154:this.$ = (function () { + $$[$0].own = $$[$0-1].own; + $$[$0].name = $$[$0-1][0]; + $$[$0].index = $$[$0-1][1]; + return $$[$0]; + }()); +break; +case 155:this.$ = $$[$0]; +break; +case 156:this.$ = (function () { + $$[$0].own = true; + return $$[$0]; + }()); +break; +case 157:this.$ = $$[$0]; +break; +case 158:this.$ = $$[$0]; +break; +case 159:this.$ = new yy.Value($$[$0]); +break; +case 160:this.$ = new yy.Value($$[$0]); +break; +case 161:this.$ = [$$[$0]]; +break; +case 162:this.$ = [$$[$0-2], $$[$0]]; +break; +case 163:this.$ = { + source: $$[$0] + }; +break; +case 164:this.$ = { + source: $$[$0], + object: true + }; +break; +case 165:this.$ = { + source: $$[$0-2], + guard: $$[$0] + }; +break; +case 166:this.$ = { + source: $$[$0-2], + guard: $$[$0], + object: true + }; +break; +case 167:this.$ = { + source: $$[$0-2], + step: $$[$0] + }; +break; +case 168:this.$ = { + source: $$[$0-4], + guard: $$[$0-2], + step: $$[$0] + }; +break; +case 169:this.$ = { + source: $$[$0-4], + step: $$[$0-2], + guard: $$[$0] + }; +break; +case 170:this.$ = new yy.Switch($$[$0-3], $$[$0-1]); +break; +case 171:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]); +break; +case 172:this.$ = new yy.Switch(null, $$[$0-1]); +break; +case 173:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]); +break; +case 174:this.$ = $$[$0]; +break; +case 175:this.$ = $$[$0-1].concat($$[$0]); +break; +case 176:this.$ = [[$$[$0-1], $$[$0]]]; +break; +case 177:this.$ = [[$$[$0-2], $$[$0-1]]]; +break; +case 178:this.$ = new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + }); +break; +case 179:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], { + type: $$[$0-2] + })); +break; +case 180:this.$ = $$[$0]; +break; +case 181:this.$ = $$[$0-2].addElse($$[$0]); +break; +case 182:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 183:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), { + type: $$[$0-1], + statement: true + }); +break; +case 184:this.$ = new yy.Op($$[$0-1], $$[$0]); +break; +case 185:this.$ = new yy.Op('-', $$[$0]); +break; +case 186:this.$ = new yy.Op('+', $$[$0]); +break; +case 187:this.$ = new yy.Op('--', $$[$0]); +break; +case 188:this.$ = new yy.Op('++', $$[$0]); +break; +case 189:this.$ = new yy.Op('--', $$[$0-1], null, true); +break; +case 190:this.$ = new yy.Op('++', $$[$0-1], null, true); +break; +case 191:this.$ = new yy.Existence($$[$0-1]); +break; +case 192:this.$ = new yy.Op('+', $$[$0-2], $$[$0]); +break; +case 193:this.$ = new yy.Op('-', $$[$0-2], $$[$0]); +break; +case 194:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 195:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 196:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 197:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]); +break; +case 198:this.$ = (function () { + if ($$[$0-1].charAt(0) === '!') { + return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert(); + } else { + return new yy.Op($$[$0-1], $$[$0-2], $$[$0]); + } + }()); +break; +case 199:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]); +break; +case 200:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]); +break; +case 201:this.$ = new yy.Extends($$[$0-2], $$[$0]); +break; +} +}, +table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[3]},{1:[2,2],6:[1,74]},{6:[1,75]},{1:[2,4],6:[2,4],26:[2,4],101:[2,4]},{4:77,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,76],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,7],6:[2,7],26:[2,7],101:[2,7],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,8],6:[2,8],26:[2,8],101:[2,8],102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,12],73:[1,100],77:[2,12],80:92,83:[1,94],84:[2,107],85:[2,12],90:[2,12],92:[2,12],101:[2,12],103:[2,12],104:[2,12],105:[2,12],109:[2,12],117:[2,12],125:[2,12],127:[2,12],128:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,13],73:[1,100],77:[2,13],80:101,83:[1,94],84:[2,107],85:[2,13],90:[2,13],92:[2,13],101:[2,13],103:[2,13],104:[2,13],105:[2,13],109:[2,13],117:[2,13],125:[2,13],127:[2,13],128:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],72:[2,14],77:[2,14],85:[2,14],90:[2,14],92:[2,14],101:[2,14],103:[2,14],104:[2,14],105:[2,14],109:[2,14],117:[2,14],125:[2,14],127:[2,14],128:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],72:[2,15],77:[2,15],85:[2,15],90:[2,15],92:[2,15],101:[2,15],103:[2,15],104:[2,15],105:[2,15],109:[2,15],117:[2,15],125:[2,15],127:[2,15],128:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],72:[2,16],77:[2,16],85:[2,16],90:[2,16],92:[2,16],101:[2,16],103:[2,16],104:[2,16],105:[2,16],109:[2,16],117:[2,16],125:[2,16],127:[2,16],128:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],72:[2,17],77:[2,17],85:[2,17],90:[2,17],92:[2,17],101:[2,17],103:[2,17],104:[2,17],105:[2,17],109:[2,17],117:[2,17],125:[2,17],127:[2,17],128:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],72:[2,18],77:[2,18],85:[2,18],90:[2,18],92:[2,18],101:[2,18],103:[2,18],104:[2,18],105:[2,18],109:[2,18],117:[2,18],125:[2,18],127:[2,18],128:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],72:[2,19],77:[2,19],85:[2,19],90:[2,19],92:[2,19],101:[2,19],103:[2,19],104:[2,19],105:[2,19],109:[2,19],117:[2,19],125:[2,19],127:[2,19],128:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],72:[2,20],77:[2,20],85:[2,20],90:[2,20],92:[2,20],101:[2,20],103:[2,20],104:[2,20],105:[2,20],109:[2,20],117:[2,20],125:[2,20],127:[2,20],128:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],72:[2,21],77:[2,21],85:[2,21],90:[2,21],92:[2,21],101:[2,21],103:[2,21],104:[2,21],105:[2,21],109:[2,21],117:[2,21],125:[2,21],127:[2,21],128:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],72:[2,22],77:[2,22],85:[2,22],90:[2,22],92:[2,22],101:[2,22],103:[2,22],104:[2,22],105:[2,22],109:[2,22],117:[2,22],125:[2,22],127:[2,22],128:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],72:[2,23],77:[2,23],85:[2,23],90:[2,23],92:[2,23],101:[2,23],103:[2,23],104:[2,23],105:[2,23],109:[2,23],117:[2,23],125:[2,23],127:[2,23],128:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23]},{1:[2,9],6:[2,9],26:[2,9],101:[2,9],103:[2,9],105:[2,9],109:[2,9],125:[2,9]},{1:[2,10],6:[2,10],26:[2,10],101:[2,10],103:[2,10],105:[2,10],109:[2,10],125:[2,10]},{1:[2,11],6:[2,11],26:[2,11],101:[2,11],103:[2,11],105:[2,11],109:[2,11],125:[2,11]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,103],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],70:[2,75],72:[2,75],73:[2,75],77:[2,75],83:[2,75],84:[2,75],85:[2,75],90:[2,75],92:[2,75],101:[2,75],103:[2,75],104:[2,75],105:[2,75],109:[2,75],117:[2,75],125:[2,75],127:[2,75],128:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],70:[2,76],72:[2,76],73:[2,76],77:[2,76],83:[2,76],84:[2,76],85:[2,76],90:[2,76],92:[2,76],101:[2,76],103:[2,76],104:[2,76],105:[2,76],109:[2,76],117:[2,76],125:[2,76],127:[2,76],128:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],70:[2,77],72:[2,77],73:[2,77],77:[2,77],83:[2,77],84:[2,77],85:[2,77],90:[2,77],92:[2,77],101:[2,77],103:[2,77],104:[2,77],105:[2,77],109:[2,77],117:[2,77],125:[2,77],127:[2,77],128:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],70:[2,78],72:[2,78],73:[2,78],77:[2,78],83:[2,78],84:[2,78],85:[2,78],90:[2,78],92:[2,78],101:[2,78],103:[2,78],104:[2,78],105:[2,78],109:[2,78],117:[2,78],125:[2,78],127:[2,78],128:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],70:[2,79],72:[2,79],73:[2,79],77:[2,79],83:[2,79],84:[2,79],85:[2,79],90:[2,79],92:[2,79],101:[2,79],103:[2,79],104:[2,79],105:[2,79],109:[2,79],117:[2,79],125:[2,79],127:[2,79],128:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],70:[2,105],72:[2,105],73:[2,105],77:[2,105],81:104,83:[2,105],84:[1,105],85:[2,105],90:[2,105],92:[2,105],101:[2,105],103:[2,105],104:[2,105],105:[2,105],109:[2,105],117:[2,105],125:[2,105],127:[2,105],128:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105]},{6:[2,55],25:[2,55],27:109,28:[1,73],44:110,48:106,49:[2,55],54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{5:115,25:[1,5]},{8:116,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:118,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:119,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:120,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:124,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,72],73:[2,72],77:[2,72],79:[1,128],83:[2,72],84:[2,72],85:[2,72],90:[2,72],92:[2,72],101:[2,72],103:[2,72],104:[2,72],105:[2,72],109:[2,72],117:[2,72],125:[2,72],127:[2,72],128:[2,72],129:[1,125],130:[1,126],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[1,127]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],49:[2,180],54:[2,180],57:[2,180],72:[2,180],77:[2,180],85:[2,180],90:[2,180],92:[2,180],101:[2,180],103:[2,180],104:[2,180],105:[2,180],109:[2,180],117:[2,180],120:[1,129],125:[2,180],127:[2,180],128:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180],135:[2,180],136:[2,180]},{5:130,25:[1,5]},{5:131,25:[1,5]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],72:[2,147],77:[2,147],85:[2,147],90:[2,147],92:[2,147],101:[2,147],103:[2,147],104:[2,147],105:[2,147],109:[2,147],117:[2,147],125:[2,147],127:[2,147],128:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147],135:[2,147],136:[2,147]},{5:132,25:[1,5]},{8:133,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,134],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,95],5:135,6:[2,95],13:121,14:122,25:[1,5],26:[2,95],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,49:[2,95],54:[2,95],57:[2,95],58:47,59:48,61:137,63:25,64:26,65:27,72:[2,95],75:[1,70],77:[2,95],79:[1,136],82:[1,28],85:[2,95],87:[1,58],88:[1,59],89:[1,57],90:[2,95],92:[2,95],100:[1,56],101:[2,95],103:[2,95],104:[2,95],105:[2,95],109:[2,95],117:[2,95],125:[2,95],127:[2,95],128:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95],135:[2,95],136:[2,95]},{8:138,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,47],6:[2,47],8:139,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,47],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,47],102:39,103:[2,47],105:[2,47],106:40,107:[1,67],108:41,109:[2,47],110:69,118:[1,42],123:37,124:[1,64],125:[2,47],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],54:[2,48],77:[2,48],101:[2,48],103:[2,48],105:[2,48],109:[2,48],125:[2,48]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],70:[2,73],72:[2,73],73:[2,73],77:[2,73],83:[2,73],84:[2,73],85:[2,73],90:[2,73],92:[2,73],101:[2,73],103:[2,73],104:[2,73],105:[2,73],109:[2,73],117:[2,73],125:[2,73],127:[2,73],128:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],70:[2,74],72:[2,74],73:[2,74],77:[2,74],83:[2,74],84:[2,74],85:[2,74],90:[2,74],92:[2,74],101:[2,74],103:[2,74],104:[2,74],105:[2,74],109:[2,74],117:[2,74],125:[2,74],127:[2,74],128:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],70:[2,29],72:[2,29],73:[2,29],77:[2,29],83:[2,29],84:[2,29],85:[2,29],90:[2,29],92:[2,29],101:[2,29],103:[2,29],104:[2,29],105:[2,29],109:[2,29],117:[2,29],125:[2,29],127:[2,29],128:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],70:[2,30],72:[2,30],73:[2,30],77:[2,30],83:[2,30],84:[2,30],85:[2,30],90:[2,30],92:[2,30],101:[2,30],103:[2,30],104:[2,30],105:[2,30],109:[2,30],117:[2,30],125:[2,30],127:[2,30],128:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],70:[2,31],72:[2,31],73:[2,31],77:[2,31],83:[2,31],84:[2,31],85:[2,31],90:[2,31],92:[2,31],101:[2,31],103:[2,31],104:[2,31],105:[2,31],109:[2,31],117:[2,31],125:[2,31],127:[2,31],128:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],70:[2,32],72:[2,32],73:[2,32],77:[2,32],83:[2,32],84:[2,32],85:[2,32],90:[2,32],92:[2,32],101:[2,32],103:[2,32],104:[2,32],105:[2,32],109:[2,32],117:[2,32],125:[2,32],127:[2,32],128:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],70:[2,33],72:[2,33],73:[2,33],77:[2,33],83:[2,33],84:[2,33],85:[2,33],90:[2,33],92:[2,33],101:[2,33],103:[2,33],104:[2,33],105:[2,33],109:[2,33],117:[2,33],125:[2,33],127:[2,33],128:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],70:[2,34],72:[2,34],73:[2,34],77:[2,34],83:[2,34],84:[2,34],85:[2,34],90:[2,34],92:[2,34],101:[2,34],103:[2,34],104:[2,34],105:[2,34],109:[2,34],117:[2,34],125:[2,34],127:[2,34],128:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],66:[2,35],67:[2,35],68:[2,35],70:[2,35],72:[2,35],73:[2,35],77:[2,35],83:[2,35],84:[2,35],85:[2,35],90:[2,35],92:[2,35],101:[2,35],103:[2,35],104:[2,35],105:[2,35],109:[2,35],117:[2,35],125:[2,35],127:[2,35],128:[2,35],131:[2,35],132:[2,35],133:[2,35],134:[2,35],135:[2,35],136:[2,35]},{4:140,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,141],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:142,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],70:[2,111],72:[2,111],73:[2,111],77:[2,111],83:[2,111],84:[2,111],85:[2,111],90:[2,111],92:[2,111],101:[2,111],103:[2,111],104:[2,111],105:[2,111],109:[2,111],117:[2,111],125:[2,111],127:[2,111],128:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],27:148,28:[1,73],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],70:[2,112],72:[2,112],73:[2,112],77:[2,112],83:[2,112],84:[2,112],85:[2,112],90:[2,112],92:[2,112],101:[2,112],103:[2,112],104:[2,112],105:[2,112],109:[2,112],117:[2,112],125:[2,112],127:[2,112],128:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112]},{25:[2,51]},{25:[2,52]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],70:[2,68],72:[2,68],73:[2,68],77:[2,68],79:[2,68],83:[2,68],84:[2,68],85:[2,68],90:[2,68],92:[2,68],101:[2,68],103:[2,68],104:[2,68],105:[2,68],109:[2,68],117:[2,68],125:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],70:[2,71],72:[2,71],73:[2,71],77:[2,71],79:[2,71],83:[2,71],84:[2,71],85:[2,71],90:[2,71],92:[2,71],101:[2,71],103:[2,71],104:[2,71],105:[2,71],109:[2,71],117:[2,71],125:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71]},{8:149,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:150,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:151,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:152,8:153,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{27:158,28:[1,73],44:159,58:160,59:161,64:154,75:[1,70],88:[1,113],89:[1,57],112:155,113:[1,156],114:157},{111:162,115:[1,163],116:[1,164]},{6:[2,90],11:168,25:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:165,77:[2,90],88:[1,113]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],70:[2,27],72:[2,27],73:[2,27],77:[2,27],83:[2,27],84:[2,27],85:[2,27],90:[2,27],92:[2,27],101:[2,27],103:[2,27],104:[2,27],105:[2,27],109:[2,27],117:[2,27],125:[2,27],127:[2,27],128:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],43:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],70:[2,28],72:[2,28],73:[2,28],77:[2,28],83:[2,28],84:[2,28],85:[2,28],90:[2,28],92:[2,28],101:[2,28],103:[2,28],104:[2,28],105:[2,28],109:[2,28],117:[2,28],125:[2,28],127:[2,28],128:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],40:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],70:[2,26],72:[2,26],73:[2,26],77:[2,26],79:[2,26],83:[2,26],84:[2,26],85:[2,26],90:[2,26],92:[2,26],101:[2,26],103:[2,26],104:[2,26],105:[2,26],109:[2,26],115:[2,26],116:[2,26],117:[2,26],125:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26]},{1:[2,6],6:[2,6],7:172,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,6],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],72:[2,24],77:[2,24],85:[2,24],90:[2,24],92:[2,24],97:[2,24],98:[2,24],101:[2,24],103:[2,24],104:[2,24],105:[2,24],109:[2,24],117:[2,24],120:[2,24],122:[2,24],125:[2,24],127:[2,24],128:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24]},{6:[1,74],26:[1,173]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],72:[2,191],77:[2,191],85:[2,191],90:[2,191],92:[2,191],101:[2,191],103:[2,191],104:[2,191],105:[2,191],109:[2,191],117:[2,191],125:[2,191],127:[2,191],128:[2,191],131:[2,191],132:[2,191],133:[2,191],134:[2,191],135:[2,191],136:[2,191]},{8:174,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:175,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:176,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:177,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:178,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:179,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:180,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:181,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],72:[2,146],77:[2,146],85:[2,146],90:[2,146],92:[2,146],101:[2,146],103:[2,146],104:[2,146],105:[2,146],109:[2,146],117:[2,146],125:[2,146],127:[2,146],128:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146],135:[2,146],136:[2,146]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],72:[2,151],77:[2,151],85:[2,151],90:[2,151],92:[2,151],101:[2,151],103:[2,151],104:[2,151],105:[2,151],109:[2,151],117:[2,151],125:[2,151],127:[2,151],128:[2,151],131:[2,151],132:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151]},{8:182,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],72:[2,145],77:[2,145],85:[2,145],90:[2,145],92:[2,145],101:[2,145],103:[2,145],104:[2,145],105:[2,145],109:[2,145],117:[2,145],125:[2,145],127:[2,145],128:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145],135:[2,145],136:[2,145]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],72:[2,150],77:[2,150],85:[2,150],90:[2,150],92:[2,150],101:[2,150],103:[2,150],104:[2,150],105:[2,150],109:[2,150],117:[2,150],125:[2,150],127:[2,150],128:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150]},{81:183,84:[1,105]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],70:[2,69],72:[2,69],73:[2,69],77:[2,69],79:[2,69],83:[2,69],84:[2,69],85:[2,69],90:[2,69],92:[2,69],101:[2,69],103:[2,69],104:[2,69],105:[2,69],109:[2,69],117:[2,69],125:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69]},{84:[2,108]},{27:184,28:[1,73]},{27:185,28:[1,73]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],27:186,28:[1,73],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],70:[2,83],72:[2,83],73:[2,83],77:[2,83],79:[2,83],83:[2,83],84:[2,83],85:[2,83],90:[2,83],92:[2,83],101:[2,83],103:[2,83],104:[2,83],105:[2,83],109:[2,83],117:[2,83],125:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],70:[2,84],72:[2,84],73:[2,84],77:[2,84],79:[2,84],83:[2,84],84:[2,84],85:[2,84],90:[2,84],92:[2,84],101:[2,84],103:[2,84],104:[2,84],105:[2,84],109:[2,84],117:[2,84],125:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84]},{8:188,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],57:[1,192],58:47,59:48,61:36,63:25,64:26,65:27,71:187,74:189,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],91:190,92:[1,191],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{69:193,70:[1,99],73:[1,100]},{81:194,84:[1,105]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],70:[2,70],72:[2,70],73:[2,70],77:[2,70],79:[2,70],83:[2,70],84:[2,70],85:[2,70],90:[2,70],92:[2,70],101:[2,70],103:[2,70],104:[2,70],105:[2,70],109:[2,70],117:[2,70],125:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70]},{6:[1,196],8:195,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,197],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],70:[2,106],72:[2,106],73:[2,106],77:[2,106],83:[2,106],84:[2,106],85:[2,106],90:[2,106],92:[2,106],101:[2,106],103:[2,106],104:[2,106],105:[2,106],109:[2,106],117:[2,106],125:[2,106],127:[2,106],128:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[1,198],86:199,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],49:[1,201],53:203,54:[1,202]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{6:[2,60],25:[2,60],26:[2,60],40:[1,205],49:[2,60],54:[2,60],57:[1,204]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:148,28:[1,73]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,50],6:[2,50],25:[2,50],26:[2,50],49:[2,50],54:[2,50],57:[2,50],72:[2,50],77:[2,50],85:[2,50],90:[2,50],92:[2,50],101:[2,50],103:[2,50],104:[2,50],105:[2,50],109:[2,50],117:[2,50],125:[2,50],127:[2,50],128:[2,50],131:[2,50],132:[2,50],133:[2,50],134:[2,50],135:[2,50],136:[2,50]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],72:[2,184],77:[2,184],85:[2,184],90:[2,184],92:[2,184],101:[2,184],102:87,103:[2,184],104:[2,184],105:[2,184],108:88,109:[2,184],110:69,117:[2,184],125:[2,184],127:[2,184],128:[2,184],131:[1,78],132:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184]},{102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],72:[2,185],77:[2,185],85:[2,185],90:[2,185],92:[2,185],101:[2,185],102:87,103:[2,185],104:[2,185],105:[2,185],108:88,109:[2,185],110:69,117:[2,185],125:[2,185],127:[2,185],128:[2,185],131:[1,78],132:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],72:[2,186],77:[2,186],85:[2,186],90:[2,186],92:[2,186],101:[2,186],102:87,103:[2,186],104:[2,186],105:[2,186],108:88,109:[2,186],110:69,117:[2,186],125:[2,186],127:[2,186],128:[2,186],131:[1,78],132:[2,186],133:[2,186],134:[2,186],135:[2,186],136:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,187],73:[2,72],77:[2,187],83:[2,72],84:[2,72],85:[2,187],90:[2,187],92:[2,187],101:[2,187],103:[2,187],104:[2,187],105:[2,187],109:[2,187],117:[2,187],125:[2,187],127:[2,187],128:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187],135:[2,187],136:[2,187]},{62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:92,83:[1,94],84:[2,107]},{62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:101,83:[1,94],84:[2,107]},{66:[2,75],67:[2,75],68:[2,75],70:[2,75],73:[2,75],83:[2,75],84:[2,75]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,188],73:[2,72],77:[2,188],83:[2,72],84:[2,72],85:[2,188],90:[2,188],92:[2,188],101:[2,188],103:[2,188],104:[2,188],105:[2,188],109:[2,188],117:[2,188],125:[2,188],127:[2,188],128:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188],135:[2,188],136:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],72:[2,189],77:[2,189],85:[2,189],90:[2,189],92:[2,189],101:[2,189],103:[2,189],104:[2,189],105:[2,189],109:[2,189],117:[2,189],125:[2,189],127:[2,189],128:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189],135:[2,189],136:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],72:[2,190],77:[2,190],85:[2,190],90:[2,190],92:[2,190],101:[2,190],103:[2,190],104:[2,190],105:[2,190],109:[2,190],117:[2,190],125:[2,190],127:[2,190],128:[2,190],131:[2,190],132:[2,190],133:[2,190],134:[2,190],135:[2,190],136:[2,190]},{8:206,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,207],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:208,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:209,25:[1,5],124:[1,210]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],49:[2,132],54:[2,132],57:[2,132],72:[2,132],77:[2,132],85:[2,132],90:[2,132],92:[2,132],96:211,97:[1,212],98:[1,213],101:[2,132],103:[2,132],104:[2,132],105:[2,132],109:[2,132],117:[2,132],125:[2,132],127:[2,132],128:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132],135:[2,132],136:[2,132]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],72:[2,144],77:[2,144],85:[2,144],90:[2,144],92:[2,144],101:[2,144],103:[2,144],104:[2,144],105:[2,144],109:[2,144],117:[2,144],125:[2,144],127:[2,144],128:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144],135:[2,144],136:[2,144]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],72:[2,152],77:[2,152],85:[2,152],90:[2,152],92:[2,152],101:[2,152],103:[2,152],104:[2,152],105:[2,152],109:[2,152],117:[2,152],125:[2,152],127:[2,152],128:[2,152],131:[2,152],132:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152]},{25:[1,214],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{119:215,121:216,122:[1,217]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],49:[2,96],54:[2,96],57:[2,96],72:[2,96],77:[2,96],85:[2,96],90:[2,96],92:[2,96],101:[2,96],103:[2,96],104:[2,96],105:[2,96],109:[2,96],117:[2,96],125:[2,96],127:[2,96],128:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96]},{8:218,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,99],5:219,6:[2,99],25:[1,5],26:[2,99],49:[2,99],54:[2,99],57:[2,99],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,99],73:[2,72],77:[2,99],79:[1,220],83:[2,72],84:[2,72],85:[2,99],90:[2,99],92:[2,99],101:[2,99],103:[2,99],104:[2,99],105:[2,99],109:[2,99],117:[2,99],125:[2,99],127:[2,99],128:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],72:[2,137],77:[2,137],85:[2,137],90:[2,137],92:[2,137],101:[2,137],102:87,103:[2,137],104:[2,137],105:[2,137],108:88,109:[2,137],110:69,117:[2,137],125:[2,137],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,46],6:[2,46],26:[2,46],101:[2,46],102:87,103:[2,46],105:[2,46],108:88,109:[2,46],110:69,125:[2,46],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,74],101:[1,221]},{4:222,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,128],25:[2,128],54:[2,128],57:[1,224],90:[2,128],91:223,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],70:[2,114],72:[2,114],73:[2,114],77:[2,114],83:[2,114],84:[2,114],85:[2,114],90:[2,114],92:[2,114],101:[2,114],103:[2,114],104:[2,114],105:[2,114],109:[2,114],115:[2,114],116:[2,114],117:[2,114],125:[2,114],127:[2,114],128:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114]},{6:[2,53],25:[2,53],53:225,54:[1,226],90:[2,53]},{6:[2,123],25:[2,123],26:[2,123],54:[2,123],85:[2,123],90:[2,123]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:227,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],85:[2,129],90:[2,129]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],40:[2,113],43:[2,113],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],70:[2,113],72:[2,113],73:[2,113],77:[2,113],79:[2,113],83:[2,113],84:[2,113],85:[2,113],90:[2,113],92:[2,113],101:[2,113],103:[2,113],104:[2,113],105:[2,113],109:[2,113],115:[2,113],116:[2,113],117:[2,113],125:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113]},{5:228,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],72:[2,140],77:[2,140],85:[2,140],90:[2,140],92:[2,140],101:[2,140],102:87,103:[1,65],104:[1,229],105:[1,66],108:88,109:[1,68],110:69,117:[2,140],125:[2,140],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],72:[2,142],77:[2,142],85:[2,142],90:[2,142],92:[2,142],101:[2,142],102:87,103:[1,65],104:[1,230],105:[1,66],108:88,109:[1,68],110:69,117:[2,142],125:[2,142],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],72:[2,148],77:[2,148],85:[2,148],90:[2,148],92:[2,148],101:[2,148],103:[2,148],104:[2,148],105:[2,148],109:[2,148],117:[2,148],125:[2,148],127:[2,148],128:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],72:[2,149],77:[2,149],85:[2,149],90:[2,149],92:[2,149],101:[2,149],102:87,103:[1,65],104:[2,149],105:[1,66],108:88,109:[1,68],110:69,117:[2,149],125:[2,149],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],72:[2,153],77:[2,153],85:[2,153],90:[2,153],92:[2,153],101:[2,153],103:[2,153],104:[2,153],105:[2,153],109:[2,153],117:[2,153],125:[2,153],127:[2,153],128:[2,153],131:[2,153],132:[2,153],133:[2,153],134:[2,153],135:[2,153],136:[2,153]},{115:[2,155],116:[2,155]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],112:231,114:157},{54:[1,232],115:[2,161],116:[2,161]},{54:[2,157],115:[2,157],116:[2,157]},{54:[2,158],115:[2,158],116:[2,158]},{54:[2,159],115:[2,159],116:[2,159]},{54:[2,160],115:[2,160],116:[2,160]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],72:[2,154],77:[2,154],85:[2,154],90:[2,154],92:[2,154],101:[2,154],103:[2,154],104:[2,154],105:[2,154],109:[2,154],117:[2,154],125:[2,154],127:[2,154],128:[2,154],131:[2,154],132:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154]},{8:233,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:234,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],53:235,54:[1,236],77:[2,53]},{6:[2,91],25:[2,91],26:[2,91],54:[2,91],77:[2,91]},{6:[2,39],25:[2,39],26:[2,39],43:[1,237],54:[2,39],77:[2,39]},{6:[2,42],25:[2,42],26:[2,42],54:[2,42],77:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],77:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],77:[2,44]},{6:[2,45],25:[2,45],26:[2,45],43:[2,45],54:[2,45],77:[2,45]},{1:[2,5],6:[2,5],26:[2,5],101:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],49:[2,25],54:[2,25],57:[2,25],72:[2,25],77:[2,25],85:[2,25],90:[2,25],92:[2,25],97:[2,25],98:[2,25],101:[2,25],103:[2,25],104:[2,25],105:[2,25],109:[2,25],117:[2,25],120:[2,25],122:[2,25],125:[2,25],127:[2,25],128:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],72:[2,192],77:[2,192],85:[2,192],90:[2,192],92:[2,192],101:[2,192],102:87,103:[2,192],104:[2,192],105:[2,192],108:88,109:[2,192],110:69,117:[2,192],125:[2,192],127:[2,192],128:[2,192],131:[1,78],132:[1,81],133:[2,192],134:[2,192],135:[2,192],136:[2,192]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],72:[2,193],77:[2,193],85:[2,193],90:[2,193],92:[2,193],101:[2,193],102:87,103:[2,193],104:[2,193],105:[2,193],108:88,109:[2,193],110:69,117:[2,193],125:[2,193],127:[2,193],128:[2,193],131:[1,78],132:[1,81],133:[2,193],134:[2,193],135:[2,193],136:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],72:[2,194],77:[2,194],85:[2,194],90:[2,194],92:[2,194],101:[2,194],102:87,103:[2,194],104:[2,194],105:[2,194],108:88,109:[2,194],110:69,117:[2,194],125:[2,194],127:[2,194],128:[2,194],131:[1,78],132:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],72:[2,195],77:[2,195],85:[2,195],90:[2,195],92:[2,195],101:[2,195],102:87,103:[2,195],104:[2,195],105:[2,195],108:88,109:[2,195],110:69,117:[2,195],125:[2,195],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[2,195],134:[2,195],135:[2,195],136:[2,195]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],72:[2,196],77:[2,196],85:[2,196],90:[2,196],92:[2,196],101:[2,196],102:87,103:[2,196],104:[2,196],105:[2,196],108:88,109:[2,196],110:69,117:[2,196],125:[2,196],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,196],135:[2,196],136:[1,85]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],72:[2,197],77:[2,197],85:[2,197],90:[2,197],92:[2,197],101:[2,197],102:87,103:[2,197],104:[2,197],105:[2,197],108:88,109:[2,197],110:69,117:[2,197],125:[2,197],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[2,197],136:[1,85]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],72:[2,198],77:[2,198],85:[2,198],90:[2,198],92:[2,198],101:[2,198],102:87,103:[2,198],104:[2,198],105:[2,198],108:88,109:[2,198],110:69,117:[2,198],125:[2,198],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,198],135:[2,198],136:[2,198]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],72:[2,183],77:[2,183],85:[2,183],90:[2,183],92:[2,183],101:[2,183],102:87,103:[1,65],104:[2,183],105:[1,66],108:88,109:[1,68],110:69,117:[2,183],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],72:[2,182],77:[2,182],85:[2,182],90:[2,182],92:[2,182],101:[2,182],102:87,103:[1,65],104:[2,182],105:[1,66],108:88,109:[1,68],110:69,117:[2,182],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],66:[2,103],67:[2,103],68:[2,103],70:[2,103],72:[2,103],73:[2,103],77:[2,103],83:[2,103],84:[2,103],85:[2,103],90:[2,103],92:[2,103],101:[2,103],103:[2,103],104:[2,103],105:[2,103],109:[2,103],117:[2,103],125:[2,103],127:[2,103],128:[2,103],131:[2,103],132:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],70:[2,80],72:[2,80],73:[2,80],77:[2,80],79:[2,80],83:[2,80],84:[2,80],85:[2,80],90:[2,80],92:[2,80],101:[2,80],103:[2,80],104:[2,80],105:[2,80],109:[2,80],117:[2,80],125:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],70:[2,81],72:[2,81],73:[2,81],77:[2,81],79:[2,81],83:[2,81],84:[2,81],85:[2,81],90:[2,81],92:[2,81],101:[2,81],103:[2,81],104:[2,81],105:[2,81],109:[2,81],117:[2,81],125:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],70:[2,82],72:[2,82],73:[2,82],77:[2,82],79:[2,82],83:[2,82],84:[2,82],85:[2,82],90:[2,82],92:[2,82],101:[2,82],103:[2,82],104:[2,82],105:[2,82],109:[2,82],117:[2,82],125:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82]},{72:[1,238]},{57:[1,192],72:[2,87],91:239,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{72:[2,88]},{8:240,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,122],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{12:[2,116],28:[2,116],30:[2,116],31:[2,116],33:[2,116],34:[2,116],35:[2,116],36:[2,116],37:[2,116],38:[2,116],45:[2,116],46:[2,116],47:[2,116],51:[2,116],52:[2,116],72:[2,116],75:[2,116],78:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],95:[2,116],99:[2,116],100:[2,116],103:[2,116],105:[2,116],107:[2,116],109:[2,116],118:[2,116],124:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116]},{12:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],72:[2,117],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],70:[2,86],72:[2,86],73:[2,86],77:[2,86],79:[2,86],83:[2,86],84:[2,86],85:[2,86],90:[2,86],92:[2,86],101:[2,86],103:[2,86],104:[2,86],105:[2,86],109:[2,86],117:[2,86],125:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],70:[2,104],72:[2,104],73:[2,104],77:[2,104],83:[2,104],84:[2,104],85:[2,104],90:[2,104],92:[2,104],101:[2,104],103:[2,104],104:[2,104],105:[2,104],109:[2,104],117:[2,104],125:[2,104],127:[2,104],128:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],72:[2,36],77:[2,36],85:[2,36],90:[2,36],92:[2,36],101:[2,36],102:87,103:[2,36],104:[2,36],105:[2,36],108:88,109:[2,36],110:69,117:[2,36],125:[2,36],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:241,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:242,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],49:[2,109],54:[2,109],57:[2,109],66:[2,109],67:[2,109],68:[2,109],70:[2,109],72:[2,109],73:[2,109],77:[2,109],83:[2,109],84:[2,109],85:[2,109],90:[2,109],92:[2,109],101:[2,109],103:[2,109],104:[2,109],105:[2,109],109:[2,109],117:[2,109],125:[2,109],127:[2,109],128:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109],136:[2,109]},{6:[2,53],25:[2,53],53:243,54:[1,226],85:[2,53]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],57:[1,244],85:[2,128],90:[2,128],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{50:245,51:[1,60],52:[1,61]},{6:[2,54],25:[2,54],26:[2,54],27:109,28:[1,73],44:110,55:246,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[1,247],25:[1,248]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61]},{8:249,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],72:[2,199],77:[2,199],85:[2,199],90:[2,199],92:[2,199],101:[2,199],102:87,103:[2,199],104:[2,199],105:[2,199],108:88,109:[2,199],110:69,117:[2,199],125:[2,199],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:250,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],72:[2,201],77:[2,201],85:[2,201],90:[2,201],92:[2,201],101:[2,201],102:87,103:[2,201],104:[2,201],105:[2,201],108:88,109:[2,201],110:69,117:[2,201],125:[2,201],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],49:[2,181],54:[2,181],57:[2,181],72:[2,181],77:[2,181],85:[2,181],90:[2,181],92:[2,181],101:[2,181],103:[2,181],104:[2,181],105:[2,181],109:[2,181],117:[2,181],125:[2,181],127:[2,181],128:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181],135:[2,181],136:[2,181]},{8:251,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],49:[2,133],54:[2,133],57:[2,133],72:[2,133],77:[2,133],85:[2,133],90:[2,133],92:[2,133],97:[1,252],101:[2,133],103:[2,133],104:[2,133],105:[2,133],109:[2,133],117:[2,133],125:[2,133],127:[2,133],128:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133],135:[2,133],136:[2,133]},{5:253,25:[1,5]},{27:254,28:[1,73]},{119:255,121:216,122:[1,217]},{26:[1,256],120:[1,257],121:258,122:[1,217]},{26:[2,174],120:[2,174],122:[2,174]},{8:260,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],94:259,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,97],5:261,6:[2,97],25:[1,5],26:[2,97],49:[2,97],54:[2,97],57:[2,97],72:[2,97],77:[2,97],85:[2,97],90:[2,97],92:[2,97],101:[2,97],102:87,103:[1,65],104:[2,97],105:[1,66],108:88,109:[1,68],110:69,117:[2,97],125:[2,97],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],49:[2,100],54:[2,100],57:[2,100],72:[2,100],77:[2,100],85:[2,100],90:[2,100],92:[2,100],101:[2,100],103:[2,100],104:[2,100],105:[2,100],109:[2,100],117:[2,100],125:[2,100],127:[2,100],128:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100]},{8:262,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],66:[2,138],67:[2,138],68:[2,138],70:[2,138],72:[2,138],73:[2,138],77:[2,138],83:[2,138],84:[2,138],85:[2,138],90:[2,138],92:[2,138],101:[2,138],103:[2,138],104:[2,138],105:[2,138],109:[2,138],117:[2,138],125:[2,138],127:[2,138],128:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138]},{6:[1,74],26:[1,263]},{8:264,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,67],12:[2,117],25:[2,67],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],54:[2,67],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,67],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{6:[1,266],25:[1,267],90:[1,265]},{6:[2,54],8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,54],26:[2,54],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[2,54],87:[1,58],88:[1,59],89:[1,57],90:[2,54],93:268,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],26:[2,53],53:269,54:[1,226]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],49:[2,178],54:[2,178],57:[2,178],72:[2,178],77:[2,178],85:[2,178],90:[2,178],92:[2,178],101:[2,178],103:[2,178],104:[2,178],105:[2,178],109:[2,178],117:[2,178],120:[2,178],125:[2,178],127:[2,178],128:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178],135:[2,178],136:[2,178]},{8:270,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:271,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{115:[2,156],116:[2,156]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],114:272},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],49:[2,163],54:[2,163],57:[2,163],72:[2,163],77:[2,163],85:[2,163],90:[2,163],92:[2,163],101:[2,163],102:87,103:[2,163],104:[1,273],105:[2,163],108:88,109:[2,163],110:69,117:[1,274],125:[2,163],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],49:[2,164],54:[2,164],57:[2,164],72:[2,164],77:[2,164],85:[2,164],90:[2,164],92:[2,164],101:[2,164],102:87,103:[2,164],104:[1,275],105:[2,164],108:88,109:[2,164],110:69,117:[2,164],125:[2,164],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,277],25:[1,278],77:[1,276]},{6:[2,54],11:168,25:[2,54],26:[2,54],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:279,42:167,44:171,46:[1,46],77:[2,54],88:[1,113]},{8:280,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,281],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],70:[2,85],72:[2,85],73:[2,85],77:[2,85],79:[2,85],83:[2,85],84:[2,85],85:[2,85],90:[2,85],92:[2,85],101:[2,85],103:[2,85],104:[2,85],105:[2,85],109:[2,85],117:[2,85],125:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85]},{8:282,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,120],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,121],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],72:[2,37],77:[2,37],85:[2,37],90:[2,37],92:[2,37],101:[2,37],102:87,103:[2,37],104:[2,37],105:[2,37],108:88,109:[2,37],110:69,117:[2,37],125:[2,37],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,283],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],85:[1,284]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],85:[2,67],90:[2,67]},{5:285,25:[1,5]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{27:109,28:[1,73],44:110,55:286,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,55],25:[2,55],26:[2,55],27:109,28:[1,73],44:110,48:287,54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,288],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:289,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:290,25:[1,5]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],72:[2,134],77:[2,134],85:[2,134],90:[2,134],92:[2,134],101:[2,134],103:[2,134],104:[2,134],105:[2,134],109:[2,134],117:[2,134],125:[2,134],127:[2,134],128:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134]},{5:291,25:[1,5]},{26:[1,292],120:[1,293],121:258,122:[1,217]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],72:[2,172],77:[2,172],85:[2,172],90:[2,172],92:[2,172],101:[2,172],103:[2,172],104:[2,172],105:[2,172],109:[2,172],117:[2,172],125:[2,172],127:[2,172],128:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172],135:[2,172],136:[2,172]},{5:294,25:[1,5]},{26:[2,175],120:[2,175],122:[2,175]},{5:295,25:[1,5],54:[1,296]},{25:[2,130],54:[2,130],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],49:[2,98],54:[2,98],57:[2,98],72:[2,98],77:[2,98],85:[2,98],90:[2,98],92:[2,98],101:[2,98],103:[2,98],104:[2,98],105:[2,98],109:[2,98],117:[2,98],125:[2,98],127:[2,98],128:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98],135:[2,98],136:[2,98]},{1:[2,101],5:297,6:[2,101],25:[1,5],26:[2,101],49:[2,101],54:[2,101],57:[2,101],72:[2,101],77:[2,101],85:[2,101],90:[2,101],92:[2,101],101:[2,101],102:87,103:[1,65],104:[2,101],105:[1,66],108:88,109:[1,68],110:69,117:[2,101],125:[2,101],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{101:[1,298]},{90:[1,299],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],70:[2,115],72:[2,115],73:[2,115],77:[2,115],83:[2,115],84:[2,115],85:[2,115],90:[2,115],92:[2,115],101:[2,115],103:[2,115],104:[2,115],105:[2,115],109:[2,115],115:[2,115],116:[2,115],117:[2,115],125:[2,115],127:[2,115],128:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],93:300,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:301,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],85:[2,124],90:[2,124]},{6:[1,266],25:[1,267],26:[1,302]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],72:[2,141],77:[2,141],85:[2,141],90:[2,141],92:[2,141],101:[2,141],102:87,103:[1,65],104:[2,141],105:[1,66],108:88,109:[1,68],110:69,117:[2,141],125:[2,141],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],72:[2,143],77:[2,143],85:[2,143],90:[2,143],92:[2,143],101:[2,143],102:87,103:[1,65],104:[2,143],105:[1,66],108:88,109:[1,68],110:69,117:[2,143],125:[2,143],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{115:[2,162],116:[2,162]},{8:303,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:304,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:305,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,89],6:[2,89],25:[2,89],26:[2,89],40:[2,89],49:[2,89],54:[2,89],57:[2,89],66:[2,89],67:[2,89],68:[2,89],70:[2,89],72:[2,89],73:[2,89],77:[2,89],83:[2,89],84:[2,89],85:[2,89],90:[2,89],92:[2,89],101:[2,89],103:[2,89],104:[2,89],105:[2,89],109:[2,89],115:[2,89],116:[2,89],117:[2,89],125:[2,89],127:[2,89],128:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89]},{11:168,27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:306,42:167,44:171,46:[1,46],88:[1,113]},{6:[2,90],11:168,25:[2,90],26:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:307,88:[1,113]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],77:[2,92]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],77:[2,40],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:308,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,119],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,38],6:[2,38],25:[2,38],26:[2,38],49:[2,38],54:[2,38],57:[2,38],72:[2,38],77:[2,38],85:[2,38],90:[2,38],92:[2,38],101:[2,38],103:[2,38],104:[2,38],105:[2,38],109:[2,38],117:[2,38],125:[2,38],127:[2,38],128:[2,38],131:[2,38],132:[2,38],133:[2,38],134:[2,38],135:[2,38],136:[2,38]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],70:[2,110],72:[2,110],73:[2,110],77:[2,110],83:[2,110],84:[2,110],85:[2,110],90:[2,110],92:[2,110],101:[2,110],103:[2,110],104:[2,110],105:[2,110],109:[2,110],117:[2,110],125:[2,110],127:[2,110],128:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],72:[2,49],77:[2,49],85:[2,49],90:[2,49],92:[2,49],101:[2,49],103:[2,49],104:[2,49],105:[2,49],109:[2,49],117:[2,49],125:[2,49],127:[2,49],128:[2,49],131:[2,49],132:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{6:[2,53],25:[2,53],26:[2,53],53:309,54:[1,202]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],72:[2,200],77:[2,200],85:[2,200],90:[2,200],92:[2,200],101:[2,200],103:[2,200],104:[2,200],105:[2,200],109:[2,200],117:[2,200],125:[2,200],127:[2,200],128:[2,200],131:[2,200],132:[2,200],133:[2,200],134:[2,200],135:[2,200],136:[2,200]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],49:[2,179],54:[2,179],57:[2,179],72:[2,179],77:[2,179],85:[2,179],90:[2,179],92:[2,179],101:[2,179],103:[2,179],104:[2,179],105:[2,179],109:[2,179],117:[2,179],120:[2,179],125:[2,179],127:[2,179],128:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179],135:[2,179],136:[2,179]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],72:[2,135],77:[2,135],85:[2,135],90:[2,135],92:[2,135],101:[2,135],103:[2,135],104:[2,135],105:[2,135],109:[2,135],117:[2,135],125:[2,135],127:[2,135],128:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],72:[2,136],77:[2,136],85:[2,136],90:[2,136],92:[2,136],97:[2,136],101:[2,136],103:[2,136],104:[2,136],105:[2,136],109:[2,136],117:[2,136],125:[2,136],127:[2,136],128:[2,136],131:[2,136],132:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],72:[2,170],77:[2,170],85:[2,170],90:[2,170],92:[2,170],101:[2,170],103:[2,170],104:[2,170],105:[2,170],109:[2,170],117:[2,170],125:[2,170],127:[2,170],128:[2,170],131:[2,170],132:[2,170],133:[2,170],134:[2,170],135:[2,170],136:[2,170]},{5:310,25:[1,5]},{26:[1,311]},{6:[1,312],26:[2,176],120:[2,176],122:[2,176]},{8:313,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],49:[2,102],54:[2,102],57:[2,102],72:[2,102],77:[2,102],85:[2,102],90:[2,102],92:[2,102],101:[2,102],103:[2,102],104:[2,102],105:[2,102],109:[2,102],117:[2,102],125:[2,102],127:[2,102],128:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102],135:[2,102],136:[2,102]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],66:[2,139],67:[2,139],68:[2,139],70:[2,139],72:[2,139],73:[2,139],77:[2,139],83:[2,139],84:[2,139],85:[2,139],90:[2,139],92:[2,139],101:[2,139],103:[2,139],104:[2,139],105:[2,139],109:[2,139],117:[2,139],125:[2,139],127:[2,139],128:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139]},{1:[2,118],6:[2,118],25:[2,118],26:[2,118],49:[2,118],54:[2,118],57:[2,118],66:[2,118],67:[2,118],68:[2,118],70:[2,118],72:[2,118],73:[2,118],77:[2,118],83:[2,118],84:[2,118],85:[2,118],90:[2,118],92:[2,118],101:[2,118],103:[2,118],104:[2,118],105:[2,118],109:[2,118],117:[2,118],125:[2,118],127:[2,118],128:[2,118],131:[2,118],132:[2,118],133:[2,118],134:[2,118],135:[2,118],136:[2,118]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],85:[2,125],90:[2,125]},{6:[2,53],25:[2,53],26:[2,53],53:314,54:[1,226]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],85:[2,126],90:[2,126]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],49:[2,165],54:[2,165],57:[2,165],72:[2,165],77:[2,165],85:[2,165],90:[2,165],92:[2,165],101:[2,165],102:87,103:[2,165],104:[2,165],105:[2,165],108:88,109:[2,165],110:69,117:[1,315],125:[2,165],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],72:[2,167],77:[2,167],85:[2,167],90:[2,167],92:[2,167],101:[2,167],102:87,103:[2,167],104:[1,316],105:[2,167],108:88,109:[2,167],110:69,117:[2,167],125:[2,167],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],49:[2,166],54:[2,166],57:[2,166],72:[2,166],77:[2,166],85:[2,166],90:[2,166],92:[2,166],101:[2,166],102:87,103:[2,166],104:[2,166],105:[2,166],108:88,109:[2,166],110:69,117:[2,166],125:[2,166],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],77:[2,93]},{6:[2,53],25:[2,53],26:[2,53],53:317,54:[1,236]},{26:[1,318],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,247],25:[1,248],26:[1,319]},{26:[1,320]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],72:[2,173],77:[2,173],85:[2,173],90:[2,173],92:[2,173],101:[2,173],103:[2,173],104:[2,173],105:[2,173],109:[2,173],117:[2,173],125:[2,173],127:[2,173],128:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173],135:[2,173],136:[2,173]},{26:[2,177],120:[2,177],122:[2,177]},{25:[2,131],54:[2,131],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],26:[1,321]},{8:322,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:323,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[1,277],25:[1,278],26:[1,324]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],77:[2,41]},{6:[2,59],25:[2,59],26:[2,59],49:[2,59],54:[2,59]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],72:[2,171],77:[2,171],85:[2,171],90:[2,171],92:[2,171],101:[2,171],103:[2,171],104:[2,171],105:[2,171],109:[2,171],117:[2,171],125:[2,171],127:[2,171],128:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171],135:[2,171],136:[2,171]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],85:[2,127],90:[2,127]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],72:[2,168],77:[2,168],85:[2,168],90:[2,168],92:[2,168],101:[2,168],102:87,103:[2,168],104:[2,168],105:[2,168],108:88,109:[2,168],110:69,117:[2,168],125:[2,168],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],72:[2,169],77:[2,169],85:[2,169],90:[2,169],92:[2,169],101:[2,169],102:87,103:[2,169],104:[2,169],105:[2,169],108:88,109:[2,169],110:69,117:[2,169],125:[2,169],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],77:[2,94]}], +defaultActions: {60:[2,51],61:[2,52],75:[2,3],94:[2,108],189:[2,88]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retreive state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; +}}; +undefined +return parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = parser; +exports.parse = function () { return parser.parse.apply(parser, arguments); } +exports.main = function commonjsMain(args) { + if (!args[1]) + throw new Error('Usage: '+args[0]+' FILE'); + if (typeof process !== 'undefined') { + var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); + } else { + var cwd = require("file").path(require("file").cwd()); + var source = cwd.join(args[1]).read({charset: "utf-8"}); + } + return exports.parser.parse(source); +} +if (typeof module !== 'undefined' && require.main === module) { + exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); +} +} \ No newline at end of file diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/repl.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/repl.js new file mode 100644 index 0000000..578dc59 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/repl.js @@ -0,0 +1,276 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, REPL_PROMPT_MULTILINE, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, multilineMode, pipedInput, readline, repl, run, stdin, stdout, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + stdin = process.openStdin(); + + stdout = process.stdout; + + CoffeeScript = require('./coffee-script'); + + readline = require('readline'); + + inspect = require('util').inspect; + + Script = require('vm').Script; + + Module = require('module'); + + REPL_PROMPT = 'coffee> '; + + REPL_PROMPT_MULTILINE = '------> '; + + REPL_PROMPT_CONTINUATION = '......> '; + + enableColours = false; + + if (process.platform !== 'win32') { + enableColours = !process.env.NODE_DISABLE_COLORS; + } + + error = function(err) { + return stdout.write((err.stack || err.toString()) + '\n'); + }; + + ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/; + + SIMPLEVAR = /(\w+)$/i; + + autocomplete = function(text) { + return completeAttribute(text) || completeVariable(text) || [[], text]; + }; + + completeAttribute = function(text) { + var all, candidates, completions, key, match, obj, prefix, _i, _len, _ref; + if (match = text.match(ACCESSOR)) { + all = match[0], obj = match[1], prefix = match[2]; + try { + obj = Script.runInThisContext(obj); + } catch (e) { + return; + } + if (obj == null) { + return; + } + obj = Object(obj); + candidates = Object.getOwnPropertyNames(obj); + while (obj = Object.getPrototypeOf(obj)) { + _ref = Object.getOwnPropertyNames(obj); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + key = _ref[_i]; + if (__indexOf.call(candidates, key) < 0) { + candidates.push(key); + } + } + } + completions = getCompletions(prefix, candidates); + return [completions, prefix]; + } + }; + + completeVariable = function(text) { + var candidates, completions, free, key, keywords, r, vars, _i, _len, _ref; + free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0; + if (text === "") { + free = ""; + } + if (free != null) { + vars = Script.runInThisContext('Object.getOwnPropertyNames(Object(this))'); + keywords = (function() { + var _i, _len, _ref1, _results; + _ref1 = CoffeeScript.RESERVED; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + r = _ref1[_i]; + if (r.slice(0, 2) !== '__') { + _results.push(r); + } + } + return _results; + })(); + candidates = vars; + for (_i = 0, _len = keywords.length; _i < _len; _i++) { + key = keywords[_i]; + if (__indexOf.call(candidates, key) < 0) { + candidates.push(key); + } + } + completions = getCompletions(free, candidates); + return [completions, free]; + } + }; + + getCompletions = function(prefix, candidates) { + var el, _i, _len, _results; + _results = []; + for (_i = 0, _len = candidates.length; _i < _len; _i++) { + el = candidates[_i]; + if (0 === el.indexOf(prefix)) { + _results.push(el); + } + } + return _results; + }; + + process.on('uncaughtException', error); + + backlog = ''; + + run = function(buffer) { + var code, returnValue, _; + buffer = buffer.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3"); + buffer = buffer.replace(/[\r\n]+$/, ""); + if (multilineMode) { + backlog += "" + buffer + "\n"; + repl.setPrompt(REPL_PROMPT_CONTINUATION); + repl.prompt(); + return; + } + if (!buffer.toString().trim() && !backlog) { + repl.prompt(); + return; + } + code = backlog += buffer; + if (code[code.length - 1] === '\\') { + backlog = "" + backlog.slice(0, -1) + "\n"; + repl.setPrompt(REPL_PROMPT_CONTINUATION); + repl.prompt(); + return; + } + repl.setPrompt(REPL_PROMPT); + backlog = ''; + try { + _ = global._; + returnValue = CoffeeScript["eval"]("_=(" + code + "\n)", { + filename: 'repl', + modulename: 'repl' + }); + if (returnValue === void 0) { + global._ = _; + } + repl.output.write("" + (inspect(returnValue, false, 2, enableColours)) + "\n"); + } catch (err) { + error(err); + } + return repl.prompt(); + }; + + if (stdin.readable && stdin.isRaw) { + pipedInput = ''; + repl = { + prompt: function() { + return stdout.write(this._prompt); + }, + setPrompt: function(p) { + return this._prompt = p; + }, + input: stdin, + output: stdout, + on: function() {} + }; + stdin.on('data', function(chunk) { + var line, lines, _i, _len, _ref; + pipedInput += chunk; + if (!/\n/.test(pipedInput)) { + return; + } + lines = pipedInput.split("\n"); + pipedInput = lines[lines.length - 1]; + _ref = lines.slice(0, -1); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + line = _ref[_i]; + if (!(line)) { + continue; + } + stdout.write("" + line + "\n"); + run(line); + } + }); + stdin.on('end', function() { + var line, _i, _len, _ref; + _ref = pipedInput.trim().split("\n"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + line = _ref[_i]; + if (!(line)) { + continue; + } + stdout.write("" + line + "\n"); + run(line); + } + stdout.write('\n'); + return process.exit(0); + }); + } else { + if (readline.createInterface.length < 3) { + repl = readline.createInterface(stdin, autocomplete); + stdin.on('data', function(buffer) { + return repl.write(buffer); + }); + } else { + repl = readline.createInterface(stdin, stdout, autocomplete); + } + } + + multilineMode = false; + + repl.input.on('keypress', function(char, key) { + var cursorPos, newPrompt; + if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) { + return; + } + cursorPos = repl.cursor; + repl.output.cursorTo(0); + repl.output.clearLine(1); + multilineMode = !multilineMode; + if (!multilineMode && backlog) { + repl._line(); + } + backlog = ''; + repl.setPrompt((newPrompt = multilineMode ? REPL_PROMPT_MULTILINE : REPL_PROMPT)); + repl.prompt(); + return repl.output.cursorTo(newPrompt.length + (repl.cursor = cursorPos)); + }); + + repl.input.on('keypress', function(char, key) { + if (!(multilineMode && repl.line)) { + return; + } + if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'd')) { + return; + } + multilineMode = false; + return repl._line(); + }); + + repl.on('attemptClose', function() { + if (multilineMode) { + multilineMode = false; + repl.output.cursorTo(0); + repl.output.clearLine(1); + repl._onLine(repl.line); + return; + } + if (backlog || repl.line) { + backlog = ''; + repl.historyIndex = -1; + repl.setPrompt(REPL_PROMPT); + repl.output.write('\n(^C again to quit)'); + return repl._line((repl.line = '')); + } else { + return repl.close(); + } + }); + + repl.on('close', function() { + repl.output.write('\n'); + return repl.input.destroy(); + }); + + repl.on('line', run); + + repl.setPrompt(REPL_PROMPT); + + repl.prompt(); + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/rewriter.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/rewriter.js new file mode 100644 index 0000000..fdfeffc --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/rewriter.js @@ -0,0 +1,349 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, + __slice = [].slice; + + exports.Rewriter = (function() { + + function Rewriter() {} + + Rewriter.prototype.rewrite = function(tokens) { + this.tokens = tokens; + this.removeLeadingNewlines(); + this.removeMidExpressionNewlines(); + this.closeOpenCalls(); + this.closeOpenIndexes(); + this.addImplicitIndentation(); + this.tagPostfixConditionals(); + this.addImplicitBraces(); + this.addImplicitParentheses(); + return this.tokens; + }; + + Rewriter.prototype.scanTokens = function(block) { + var i, token, tokens; + tokens = this.tokens; + i = 0; + while (token = tokens[i]) { + i += block.call(this, token, i, tokens); + } + return true; + }; + + Rewriter.prototype.detectEnd = function(i, condition, action) { + var levels, token, tokens, _ref, _ref1; + tokens = this.tokens; + levels = 0; + while (token = tokens[i]) { + if (levels === 0 && condition.call(this, token, i)) { + return action.call(this, token, i); + } + if (!token || levels < 0) { + return action.call(this, token, i - 1); + } + if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) { + levels += 1; + } else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) { + levels -= 1; + } + i += 1; + } + return i - 1; + }; + + Rewriter.prototype.removeLeadingNewlines = function() { + var i, tag, _i, _len, _ref; + _ref = this.tokens; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + tag = _ref[i][0]; + if (tag !== 'TERMINATOR') { + break; + } + } + if (i) { + return this.tokens.splice(0, i); + } + }; + + Rewriter.prototype.removeMidExpressionNewlines = function() { + return this.scanTokens(function(token, i, tokens) { + var _ref; + if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) { + return 1; + } + tokens.splice(i, 1); + return 0; + }); + }; + + Rewriter.prototype.closeOpenCalls = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')'; + }; + action = function(token, i) { + return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'CALL_START') { + this.detectEnd(i + 1, condition, action); + } + return 1; + }); + }; + + Rewriter.prototype.closeOpenIndexes = function() { + var action, condition; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === ']' || _ref === 'INDEX_END'; + }; + action = function(token, i) { + return token[0] = 'INDEX_END'; + }; + return this.scanTokens(function(token, i) { + if (token[0] === 'INDEX_START') { + this.detectEnd(i + 1, condition, action); + } + return 1; + }); + }; + + Rewriter.prototype.addImplicitBraces = function() { + var action, condition, sameLine, stack, start, startIndent, startIndex, startsLine; + stack = []; + start = null; + startsLine = null; + sameLine = true; + startIndent = 0; + startIndex = 0; + condition = function(token, i) { + var one, tag, three, two, _ref, _ref1; + _ref = this.tokens.slice(i + 1, +(i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2]; + if ('HERECOMMENT' === (one != null ? one[0] : void 0)) { + return false; + } + tag = token[0]; + if (__indexOf.call(LINEBREAKS, tag) >= 0) { + sameLine = false; + } + return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine && !(i - startIndex === 1))) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT')); + }; + action = function(token, i) { + var tok; + tok = this.generate('}', '}', token[2]); + return this.tokens.splice(i, 0, tok); + }; + return this.scanTokens(function(token, i, tokens) { + var ago, idx, prevTag, tag, tok, value, _ref, _ref1; + if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) { + stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]); + return 1; + } + if (__indexOf.call(EXPRESSION_END, tag) >= 0) { + start = stack.pop(); + return 1; + } + if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) { + return 1; + } + sameLine = true; + startIndex = i + 1; + stack.push(['{']); + idx = ago === '@' ? i - 2 : i - 1; + while (this.tag(idx - 2) === 'HERECOMMENT') { + idx -= 2; + } + prevTag = this.tag(idx - 1); + startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0); + value = new String('{'); + value.generated = true; + tok = this.generate('{', value, token[2]); + tokens.splice(idx, 0, tok); + this.detectEnd(i + 2, condition, action); + return 2; + }); + }; + + Rewriter.prototype.addImplicitParentheses = function() { + var action, condition, noCall, seenControl, seenSingle; + noCall = seenSingle = seenControl = false; + condition = function(token, i) { + var post, tag, _ref, _ref1; + tag = token[0]; + if (!seenSingle && token.fromThen) { + return true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') { + seenSingle = true; + } + if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') { + seenControl = true; + } + if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') { + return true; + } + return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{'))); + }; + action = function(token, i) { + return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2])); + }; + return this.scanTokens(function(token, i, tokens) { + var callObject, current, next, prev, tag, _ref, _ref1, _ref2; + tag = token[0]; + if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') { + noCall = true; + } + _ref = tokens.slice(i - 1, +(i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2]; + callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0); + seenSingle = false; + seenControl = false; + if (__indexOf.call(LINEBREAKS, tag) >= 0) { + noCall = false; + } + if (prev && !prev.spaced && tag === '?') { + token.call = true; + } + if (token.fromThen) { + return 1; + } + if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) { + return 1; + } + tokens.splice(i, 0, this.generate('CALL_START', '(', token[2])); + this.detectEnd(i + 1, condition, action); + if (prev[0] === '?') { + prev[0] = 'FUNC_EXIST'; + } + return 2; + }); + }; + + Rewriter.prototype.addImplicitIndentation = function() { + var action, condition, indent, outdent, starter; + starter = indent = outdent = null; + condition = function(token, i) { + var _ref; + return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN')); + }; + action = function(token, i) { + return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent); + }; + return this.scanTokens(function(token, i, tokens) { + var tag, _ref, _ref1; + tag = token[0]; + if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') { + tokens.splice(i, 1); + return 0; + } + if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') { + tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token)))); + return 2; + } + if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) { + tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token)))); + return 4; + } + if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) { + starter = tag; + _ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1]; + if (starter === 'THEN') { + indent.fromThen = true; + } + tokens.splice(i + 1, 0, indent); + this.detectEnd(i + 2, condition, action); + if (tag === 'THEN') { + tokens.splice(i, 1); + } + return 1; + } + return 1; + }); + }; + + Rewriter.prototype.tagPostfixConditionals = function() { + var action, condition, original; + original = null; + condition = function(token, i) { + var _ref; + return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT'; + }; + action = function(token, i) { + if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) { + return original[0] = 'POST_' + original[0]; + } + }; + return this.scanTokens(function(token, i) { + if (token[0] !== 'IF') { + return 1; + } + original = token; + this.detectEnd(i + 1, condition, action); + return 1; + }); + }; + + Rewriter.prototype.indentation = function(token, implicit) { + var indent, outdent; + if (implicit == null) { + implicit = false; + } + indent = ['INDENT', 2, token[2]]; + outdent = ['OUTDENT', 2, token[2]]; + if (implicit) { + indent.generated = outdent.generated = true; + } + return [indent, outdent]; + }; + + Rewriter.prototype.generate = function(tag, value, line) { + var tok; + tok = [tag, value, line]; + tok.generated = true; + return tok; + }; + + Rewriter.prototype.tag = function(i) { + var _ref; + return (_ref = this.tokens[i]) != null ? _ref[0] : void 0; + }; + + return Rewriter; + + })(); + + BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']]; + + exports.INVERSES = INVERSES = {}; + + EXPRESSION_START = []; + + EXPRESSION_END = []; + + for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) { + _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1]; + EXPRESSION_START.push(INVERSES[rite] = left); + EXPRESSION_END.push(INVERSES[left] = rite); + } + + EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); + + IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']; + + IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++']; + + IMPLICIT_UNSPACED_CALL = ['+', '-']; + + IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']; + + IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']; + + SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']; + + SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']; + + LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']; + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/lib/coffee-script/scope.js b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/scope.js new file mode 100644 index 0000000..3f35dbf --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/lib/coffee-script/scope.js @@ -0,0 +1,146 @@ +// Generated by CoffeeScript 1.4.0 +(function() { + var Scope, extend, last, _ref; + + _ref = require('./helpers'), extend = _ref.extend, last = _ref.last; + + exports.Scope = Scope = (function() { + + Scope.root = null; + + function Scope(parent, expressions, method) { + this.parent = parent; + this.expressions = expressions; + this.method = method; + this.variables = [ + { + name: 'arguments', + type: 'arguments' + } + ]; + this.positions = {}; + if (!this.parent) { + Scope.root = this; + } + } + + Scope.prototype.add = function(name, type, immediate) { + if (this.shared && !immediate) { + return this.parent.add(name, type, immediate); + } + if (Object.prototype.hasOwnProperty.call(this.positions, name)) { + return this.variables[this.positions[name]].type = type; + } else { + return this.positions[name] = this.variables.push({ + name: name, + type: type + }) - 1; + } + }; + + Scope.prototype.namedMethod = function() { + if (this.method.name || !this.parent) { + return this.method; + } + return this.parent.namedMethod(); + }; + + Scope.prototype.find = function(name) { + if (this.check(name)) { + return true; + } + this.add(name, 'var'); + return false; + }; + + Scope.prototype.parameter = function(name) { + if (this.shared && this.parent.check(name, true)) { + return; + } + return this.add(name, 'param'); + }; + + Scope.prototype.check = function(name) { + var _ref1; + return !!(this.type(name) || ((_ref1 = this.parent) != null ? _ref1.check(name) : void 0)); + }; + + Scope.prototype.temporary = function(name, index) { + if (name.length > 1) { + return '_' + name + (index > 1 ? index - 1 : ''); + } else { + return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a'); + } + }; + + Scope.prototype.type = function(name) { + var v, _i, _len, _ref1; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.name === name) { + return v.type; + } + } + return null; + }; + + Scope.prototype.freeVariable = function(name, reserve) { + var index, temp; + if (reserve == null) { + reserve = true; + } + index = 0; + while (this.check((temp = this.temporary(name, index)))) { + index++; + } + if (reserve) { + this.add(temp, 'var', true); + } + return temp; + }; + + Scope.prototype.assign = function(name, value) { + this.add(name, { + value: value, + assigned: true + }, true); + return this.hasAssignments = true; + }; + + Scope.prototype.hasDeclarations = function() { + return !!this.declaredVariables().length; + }; + + Scope.prototype.declaredVariables = function() { + var realVars, tempVars, v, _i, _len, _ref1; + realVars = []; + tempVars = []; + _ref1 = this.variables; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type === 'var') { + (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name); + } + } + return realVars.sort().concat(tempVars.sort()); + }; + + Scope.prototype.assignedVariables = function() { + var v, _i, _len, _ref1, _results; + _ref1 = this.variables; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + v = _ref1[_i]; + if (v.type.assigned) { + _results.push("" + v.name + " = " + v.type.value); + } + } + return _results; + }; + + return Scope; + + })(); + +}).call(this); diff --git a/node_modules/jade/node_modules/coffee-script/package.json b/node_modules/jade/node_modules/coffee-script/package.json new file mode 100644 index 0000000..938ef19 --- /dev/null +++ b/node_modules/jade/node_modules/coffee-script/package.json @@ -0,0 +1,50 @@ +{ + "name": "coffee-script", + "description": "Unfancy JavaScript", + "keywords": [ + "javascript", + "language", + "coffeescript", + "compiler" + ], + "author": { + "name": "Jeremy Ashkenas" + }, + "version": "1.4.0", + "licenses": [ + { + "type": "MIT", + "url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE" + } + ], + "engines": { + "node": ">=0.4.0" + }, + "directories": { + "lib": "./lib/coffee-script" + }, + "main": "./lib/coffee-script/coffee-script", + "bin": { + "coffee": "./bin/coffee", + "cake": "./bin/cake" + }, + "scripts": { + "test": "node ./bin/cake test" + }, + "homepage": "http://coffeescript.org", + "bugs": "https://github.com/jashkenas/coffee-script/issues", + "repository": { + "type": "git", + "url": "git://github.com/jashkenas/coffee-script.git" + }, + "devDependencies": { + "uglify-js": ">=1.0.0", + "jison": ">=0.2.0" + }, + "readme": "\n {\n } } {\n { { } }\n } }{ {\n { }{ } } _____ __ __\n ( }{ }{ { ) / ____| / _|/ _|\n .- { { } { }} -. | | ___ | |_| |_ ___ ___\n ( ( } { } { } } ) | | / _ \\| _| _/ _ \\/ _ \\\n |`-..________ ..-'| | |___| (_) | | | || __/ __/\n | | \\_____\\___/|_| |_| \\___|\\___|\n | ;--.\n | (__ \\ _____ _ _\n | | ) ) / ____| (_) | |\n | |/ / | (___ ___ _ __ _ _ __ | |_\n | ( / \\___ \\ / __| '__| | '_ \\| __|\n | |/ ____) | (__| | | | |_) | |_\n | | |_____/ \\___|_| |_| .__/ \\__|\n `-.._________..-' | |\n |_|\n\n\n CoffeeScript is a little language that compiles into JavaScript.\n\n Install Node.js, and then the CoffeeScript compiler:\n sudo bin/cake install\n\n Or, if you have the Node Package Manager installed:\n npm install -g coffee-script\n (Leave off the -g if you don't wish to install globally.)\n\n Execute a script:\n coffee /path/to/script.coffee\n\n Compile a script:\n coffee -c /path/to/script.coffee\n\n For documentation, usage, and examples, see:\n http://coffeescript.org/\n\n To suggest a feature, report a bug, or general discussion:\n http://github.com/jashkenas/coffee-script/issues/\n\n If you'd like to chat, drop by #coffeescript on Freenode IRC,\n or on webchat.freenode.net.\n\n The source repository:\n git://github.com/jashkenas/coffee-script.git\n\n All contributors are listed here:\n http://github.com/jashkenas/coffee-script/contributors\n", + "_id": "coffee-script@1.4.0", + "dist": { + "shasum": "5e3bc8aac26c01a8e27bf107722c5655f5ad7d36" + }, + "_from": "coffee-script@~1.4.0" +} diff --git a/node_modules/jade/node_modules/commander/.npmignore b/node_modules/jade/node_modules/commander/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/jade/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/jade/node_modules/commander/.travis.yml b/node_modules/jade/node_modules/commander/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/jade/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/jade/node_modules/commander/History.md b/node_modules/jade/node_modules/commander/History.md new file mode 100644 index 0000000..4961d2e --- /dev/null +++ b/node_modules/jade/node_modules/commander/History.md @@ -0,0 +1,107 @@ + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/jade/node_modules/commander/Makefile b/node_modules/jade/node_modules/commander/Makefile new file mode 100644 index 0000000..0074625 --- /dev/null +++ b/node_modules/jade/node_modules/commander/Makefile @@ -0,0 +1,7 @@ + +TESTS = $(shell find test/test.*.js) + +test: + @./test/run $(TESTS) + +.PHONY: test \ No newline at end of file diff --git a/node_modules/jade/node_modules/commander/Readme.md b/node_modules/jade/node_modules/commander/Readme.md new file mode 100644 index 0000000..b8328c3 --- /dev/null +++ b/node_modules/jade/node_modules/commander/Readme.md @@ -0,0 +1,262 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## 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. \ No newline at end of file diff --git a/node_modules/jade/node_modules/commander/index.js b/node_modules/jade/node_modules/commander/index.js new file mode 100644 index 0000000..06ec1e4 --- /dev/null +++ b/node_modules/jade/node_modules/commander/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/commander'); \ No newline at end of file diff --git a/node_modules/jade/node_modules/commander/lib/commander.js b/node_modules/jade/node_modules/commander/lib/commander.js new file mode 100644 index 0000000..5ba87eb --- /dev/null +++ b/node_modules/jade/node_modules/commander/lib/commander.js @@ -0,0 +1,1026 @@ + +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , tty = require('tty') + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this.args = []; + this.name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + return cmd; +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self.args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self.args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this.name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + self.args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self.args.length) { + args[self.args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // store raw args + this.rawArgs = argv; + + // guess name + if (!this.name) this.name = basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + this.args = parsed.args; + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0]) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || '-' == arg[0]) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this.args.length ? ' ' + args : ''); + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return cmd.name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args + + (cmd.description() + ? '\n' + cmd.description() + : ''); + }).join('\n\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this.name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + process.stdin.resume(); + tty.setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.removeAllListeners('keypress'); + tty.setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + process.stdout.write(cmd.helpInformation()); + cmd.emit('--help'); + process.exit(0); + } + } +} diff --git a/node_modules/jade/node_modules/commander/package.json b/node_modules/jade/node_modules/commander/package.json new file mode 100644 index 0000000..764dece --- /dev/null +++ b/node_modules/jade/node_modules/commander/package.json @@ -0,0 +1,34 @@ +{ + "name": "commander", + "version": "0.6.1", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": {}, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.4.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "_id": "commander@0.6.1", + "_from": "commander@0.6.1" +} diff --git a/node_modules/jade/node_modules/mkdirp/.npmignore b/node_modules/jade/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/jade/node_modules/mkdirp/.travis.yml b/node_modules/jade/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/jade/node_modules/mkdirp/LICENSE b/node_modules/jade/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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. diff --git a/node_modules/jade/node_modules/mkdirp/README.markdown b/node_modules/jade/node_modules/mkdirp/README.markdown new file mode 100644 index 0000000..40de04f --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/README.markdown @@ -0,0 +1,61 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/node_modules/jade/node_modules/mkdirp/examples/pow.js b/node_modules/jade/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/jade/node_modules/mkdirp/index.js b/node_modules/jade/node_modules/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/jade/node_modules/mkdirp/package.json b/node_modules/jade/node_modules/mkdirp/package.json new file mode 100644 index 0000000..8772a1f --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/package.json @@ -0,0 +1,35 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.4", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "http://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "~0.2.4" + }, + "license": "MIT/X11", + "engines": { + "node": "*" + }, + "readme": "mkdirp\n======\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\nexample\n=======\n\npow.js\n------\n var mkdirp = require('mkdirp');\n \n mkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n });\n\nOutput\n pow!\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\nmethods\n=======\n\nvar mkdirp = require('mkdirp');\n\nmkdirp(dir, mode, cb)\n---------------------\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nmkdirp.sync(dir, mode)\n----------------------\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n npm install mkdirp\n\nlicense\n=======\n\nMIT/X11\n", + "_id": "mkdirp@0.3.4", + "dist": { + "shasum": "c039e4133209fbeba85f2acd7e8dc6f5838a8c21" + }, + "_from": "mkdirp@0.3.x" +} diff --git a/node_modules/jade/node_modules/mkdirp/test/chmod.js b/node_modules/jade/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/clobber.js b/node_modules/jade/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/mkdirp.js b/node_modules/jade/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/perm.js b/node_modules/jade/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/perm_sync.js b/node_modules/jade/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/race.js b/node_modules/jade/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/rel.js b/node_modules/jade/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/return.js b/node_modules/jade/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/return_sync.js b/node_modules/jade/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/root.js b/node_modules/jade/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/sync.js b/node_modules/jade/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..7530cad --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/umask.js b/node_modules/jade/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/jade/node_modules/mkdirp/test/umask_sync.js b/node_modules/jade/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..35bd5cb --- /dev/null +++ b/node_modules/jade/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }); + }); +}); diff --git a/node_modules/jade/package.json b/node_modules/jade/package.json new file mode 100644 index 0000000..0e46d88 --- /dev/null +++ b/node_modules/jade/package.json @@ -0,0 +1,48 @@ +{ + "name": "jade", + "description": "Jade template engine", + "version": "0.28.1", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/jade" + }, + "main": "./index.js", + "bin": { + "jade": "./bin/jade" + }, + "man": [ + "./jade.1" + ], + "dependencies": { + "commander": "0.6.1", + "mkdirp": "0.3.x", + "coffee-script": "~1.4.0" + }, + "devDependencies": { + "mocha": "*", + "markdown": "*", + "stylus": "*", + "uubench": "*", + "should": "*", + "less": "*", + "uglify-js": "*" + }, + "component": { + "scripts": { + "jade": "runtime.js" + } + }, + "scripts": { + "prepublish": "npm prune" + }, + "readme": " [![Build Status](https://secure.travis-ci.org/visionmedia/jade.png)](http://travis-ci.org/visionmedia/jade)\n\n# Jade - template engine\n\n Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com)\n and implemented with JavaScript for [node](http://nodejs.org). For discussion join the [Google Group](http://groups.google.com/group/jadejs).\n\n## Test drive\n\n You can test drive Jade online [here](http://naltatis.github.com/jade-syntax-docs).\n\n## README Contents\n\n- [Features](#a1)\n- [Implementations](#a2)\n- [Installation](#a3)\n- [Browser Support](#a4)\n- [Public API](#a5)\n- [Syntax](#a6)\n - [Line Endings](#a6-1)\n - [Tags](#a6-2)\n - [Tag Text](#a6-3)\n - [Comments](#a6-4)\n - [Block Comments](#a6-5)\n - [Nesting](#a6-6)\n - [Block Expansion](#a6-7)\n - [Case](#a6-8)\n - [Attributes](#a6-9)\n - [HTML](#a6-10)\n - [Doctypes](#a6-11)\n- [Filters](#a7)\n- [Code](#a8)\n- [Iteration](#a9)\n- [Conditionals](#a10)\n- [Template inheritance](#a11)\n- [Block append / prepend](#a12)\n- [Includes](#a13)\n- [Mixins](#a14)\n- [Generated Output](#a15)\n- [Example Makefile](#a16)\n- [jade(1)](#a17)\n- [Tutorials](#a18)\n- [License](#a19)\n\n\n## Features\n\n - client-side support\n - great readability\n - flexible indentation\n - block-expansion\n - mixins\n - static includes\n - attribute interpolation\n - code is escaped by default for security\n - contextual error reporting at compile & run time\n - executable for compiling jade templates via the command line\n - html 5 mode (the default doctype)\n - optional memory caching\n - combine dynamic and static tag classes\n - parse tree manipulation via _filters_\n - template inheritance\n - block append / prepend\n - supports [Express JS](http://expressjs.com) out of the box\n - transparent iteration over objects, arrays, and even non-enumerables via `each`\n - block comments\n - no tag prefix\n - filters\n - :stylus must have [stylus](http://github.com/LearnBoost/stylus) installed\n - :less must have [less.js](http://github.com/cloudhead/less.js) installed\n - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js), [node-discount](http://github.com/visionmedia/node-discount), or [marked](http://github.com/chjj/marked) installed\n - :cdata\n - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed\n - [Emacs Mode](https://github.com/brianc/jade-mode)\n - [Vim Syntax](https://github.com/digitaltoad/vim-jade)\n - [TextMate Bundle](http://github.com/miksago/jade-tmbundle)\n - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode)\n - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs)\n - [html2jade](https://github.com/donpark/html2jade) converter\n\n\n## Implementations\n\n - [php](http://github.com/everzet/jade.php)\n - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html)\n - [ruby](http://github.com/stonean/slim)\n - [python](https://github.com/SyrusAkbary/pyjade)\n - [java](https://github.com/neuland/jade4j)\n\n\n## Installation\n\nvia npm:\n\n```bash\n$ npm install jade\n```\n\n\n## Browser Support\n\n To compile jade to a single file compatible for client-side use simply execute:\n\n```bash\n$ make jade.js\n```\n\n Alternatively, if uglifyjs is installed via npm (`npm install uglify-js`) you may execute the following which will create both files. However each release builds these for you.\n\n```bash\n$ make jade.min.js\n```\n\n By default Jade instruments templates with line number statements such as `__.lineno = 3` for debugging purposes. When used in a browser it's useful to minimize this boiler plate, you can do so by passing the option `{ compileDebug: false }`. The following template\n\n```jade\np Hello #{name}\n```\n\n Can then be as small as the following generated function:\n\n```js\nfunction anonymous(locals, attrs, escape, rethrow) {\n var buf = [];\n with (locals || {}) {\n var interp;\n buf.push('\\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\\n

    ');\n }\n return buf.join(\"\");\n}\n```\n\n Through the use of Jade's `./runtime.js` you may utilize these pre-compiled templates on the client-side _without_ Jade itself, all you need is the associated utility functions (in runtime.js), which are then available as `jade.attrs`, `jade.escape` etc. To enable this you should pass `{ client: true }` to `jade.compile()` to tell Jade to reference the helper functions\n via `jade.attrs`, `jade.escape` etc.\n\n```js\nfunction anonymous(locals, attrs, escape, rethrow) {\n var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;\n var buf = [];\n with (locals || {}) {\n var interp;\n buf.push('\\n

    Hello ' + escape((interp = name) == null ? '' : interp) + '\\n

    ');\n }\n return buf.join(\"\");\n}\n```\n\n
    \n## Public API\n\n```js\nvar jade = require('jade');\n\n// Compile a function\nvar fn = jade.compile('string of jade', options);\nfn(locals);\n```\n\n### Options\n\n - `self` Use a `self` namespace to hold the locals _(false by default)_\n - `locals` Local variable object\n - `filename` Used in exceptions, and required when using includes\n - `debug` Outputs tokens and function body generated\n - `compiler` Compiler to replace jade's default\n - `compileDebug` When `false` no debug instrumentation is compiled\n - `pretty` Add pretty-indentation whitespace to output _(false by default)_\n\n\n## Syntax\n\n\n### Line Endings\n\n**CRLF** and **CR** are converted to **LF** before parsing.\n\n\n### Tags\n\nA tag is simply a leading word:\n\n```jade\nhtml\n```\n\nfor example is converted to ``\n\ntags can also have ids:\n\n```jade\ndiv#container\n```\n\nwhich would render `
    `\n\nhow about some classes?\n\n```jade\ndiv.user-details\n```\n\nrenders `
    `\n\nmultiple classes? _and_ an id? sure:\n\n```jade\ndiv#foo.bar.baz\n```\n\nrenders `
    `\n\ndiv div div sure is annoying, how about:\n\n```jade\n#foo\n.bar\n```\n\nwhich is syntactic sugar for what we have already been doing, and outputs:\n\n```html\n
    \n```\n\n
    \n### Tag Text\n\nSimply place some content after the tag:\n\n```jade\np wahoo!\n```\n\nrenders `

    wahoo!

    `.\n\nwell cool, but how about large bodies of text:\n\n```jade\np\n | foo bar baz\n | rawr rawr\n | super cool\n | go jade go\n```\n\nrenders `

    foo bar baz rawr.....

    `\n\ninterpolation? yup! both types of text can utilize interpolation,\nif we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following:\n\n```jade\n#user #{name} <#{email}>\n```\n\noutputs `
    tj <tj@vision-media.ca>
    `\n\nActually want `#{}` for some reason? escape it!\n\n```jade\np \\#{something}\n```\n\nnow we have `

    #{something}

    `\n\nWe can also utilize the unescaped variant `!{html}`, so the following\nwill result in a literal script tag:\n\n```jade\n- var html = \"\"\n| !{html}\n```\n\nNested tags that also contain text can optionally use a text block:\n\n```jade\nlabel\n | Username:\n input(name='user[name]')\n```\n\nor immediate tag text:\n\n```jade\nlabel Username:\n input(name='user[name]')\n```\n\nTags that accept _only_ text such as `script` and `style` do not\nneed the leading `|` character, for example:\n\n```jade\nhtml\n head\n title Example\n script\n if (foo) {\n bar();\n } else {\n baz();\n }\n```\n\nOnce again as an alternative, we may use a trailing `.` to indicate a text block, for example:\n\n```jade\np.\n foo asdf\n asdf\n asdfasdfaf\n asdf\n asd.\n```\n\noutputs:\n\n```html\n

    foo asdf\nasdf\n asdfasdfaf\n asdf\nasd.\n

    \n```\n\nThis however differs from a trailing `.` followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal:\n\n```jade\np .\n```\n\noutputs:\n\n```html\n

    .

    \n```\n\nIt should be noted that text blocks should be doubled escaped. For example if you desire the following output.\n\n```html\n

    foo\\bar

    \n```\n\nuse:\n\n```jade\np.\n foo\\\\bar\n```\n\n
    \n### Comments\n\nSingle line comments currently look the same as JavaScript comments,\naka `//` and must be placed on their own line:\n\n```jade\n// just some paragraphs\np foo\np bar\n```\n\nwould output\n\n```html\n\n

    foo

    \n

    bar

    \n```\n\nJade also supports unbuffered comments, by simply adding a hyphen:\n\n```jade\n//- will not output within markup\np foo\np bar\n```\n\noutputting\n\n```html\n

    foo

    \n

    bar

    \n```\n\n
    \n### Block Comments\n\n A block comment is legal as well:\n\n```jade\nbody\n //\n #content\n h1 Example\n```\n\noutputting\n\n```html\n\n \n\n```\n\nJade supports conditional-comments as well, for example:\n\n```jade\nhead\n //if lt IE 8\n script(src='/ie-sucks.js')\n```\n\noutputs:\n\n```html\n\n \n\n```\n\n\n### Nesting\n\n Jade supports nesting to define the tags in a natural way:\n\n```jade\nul\n li.first\n a(href='#') foo\n li\n a(href='#') bar\n li.last\n a(href='#') baz\n```\n\n\n### Block Expansion\n\n Block expansion allows you to create terse single-line nested tags,\n the following example is equivalent to the nesting example above.\n\n```jade\nul\n li.first: a(href='#') foo\n li: a(href='#') bar\n li.last: a(href='#') baz\n```\n\n\n### Case\n\n The case statement takes the following form:\n\n```jade\nhtml\n body\n friends = 10\n case friends\n when 0\n p you have no friends\n when 1\n p you have a friend\n default\n p you have #{friends} friends\n```\n\n Block expansion may also be used:\n\n```jade\nfriends = 5\n\nhtml\n body\n case friends\n when 0: p you have no friends\n when 1: p you have a friend\n default: p you have #{friends} friends\n```\n\n\n### Attributes\n\nJade currently supports `(` and `)` as attribute delimiters.\n\n```jade\na(href='/login', title='View login page') Login\n```\n\nWhen a value is `undefined` or `null` the attribute is _not_ added,\nso this is fine, it will not compile `something=\"null\"`.\n\n```jade\ndiv(something=null)\n```\n\nBoolean attributes are also supported:\n\n```jade\ninput(type=\"checkbox\", checked)\n```\n\nBoolean attributes with code will only output the attribute when `true`:\n\n```jade\ninput(type=\"checkbox\", checked=someValue)\n```\n\nMultiple lines work too:\n\n```jade\ninput(type='checkbox',\n name='agreement',\n checked)\n```\n\nMultiple lines without the comma work fine:\n\n```jade\ninput(type='checkbox'\n name='agreement'\n checked)\n```\n\nFunky whitespace? fine:\n\n```jade\ninput(\n type='checkbox'\n name='agreement'\n checked)\n```\n\nColons work:\n\n```jade\nrss(xmlns:atom=\"atom\")\n```\n\nSuppose we have the `user` local `{ id: 12, name: 'tobi' }`\nand we wish to create an anchor tag with `href` pointing to \"/user/12\"\nwe could use regular javascript concatenation:\n\n```jade\na(href='/user/' + user.id)= user.name\n```\n\nor we could use jade's interpolation, which I added because everyone\nusing Ruby or CoffeeScript seems to think this is legal js..:\n\n```jade\na(href='/user/#{user.id}')= user.name\n```\n\nThe `class` attribute is special-cased when an array is given,\nallowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly:\n\n```jade\nbody(class=bodyClasses)\n```\n\n\n### HTML\n\n Inline html is fine, we can use the pipe syntax to\n write arbitrary text, in this case some html:\n\n```jade\nhtml\n body\n |

    Title

    \n |

    foo bar baz

    \n```\n\n Or we can use the trailing `.` to indicate to Jade that we\n only want text in this block, allowing us to omit the pipes:\n\n```jade\nhtml\n body.\n

    Title

    \n

    foo bar baz

    \n```\n\n Both of these examples yield the same result:\n\n```html\n

    Title

    \n

    foo bar baz

    \n\n```\n\n The same rule applies for anywhere you can have text\n in jade, raw html is fine:\n\n```jade\nhtml\n body\n h1 User #{name}\n```\n\n
    \n### Doctypes\n\nTo add a doctype simply use `!!!`, or `doctype` followed by an optional value:\n\n```jade\n!!!\n```\n\nor\n\n```jade\ndoctype\n```\n\nWill output the _html 5_ doctype, however:\n\n```jade\n!!! transitional\n```\n\nWill output the _transitional_ doctype.\n\nDoctypes are case-insensitive, so the following are equivalent:\n\n```jade\ndoctype Basic\ndoctype basic\n```\n\nit's also possible to simply pass a doctype literal:\n\n```jade\ndoctype html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\n```\n\nyielding:\n\n```html\n\n```\n\nBelow are the doctypes defined by default, which can easily be extended:\n\n```js\nvar doctypes = exports.doctypes = {\n '5': '',\n 'default': '',\n 'xml': '',\n 'transitional': '',\n 'strict': '',\n 'frameset': '',\n '1.1': '',\n 'basic': '',\n 'mobile': ''\n};\n```\n\nTo alter the default simply change:\n\n```js\njade.doctypes.default = 'whatever you want';\n```\n\n\n## Filters\n\nFilters are prefixed with `:`, for example `:markdown` and\npass the following block of text to an arbitrary function for processing. View the _features_\nat the top of this document for available filters.\n\n```jade\nbody\n :markdown\n Woah! jade _and_ markdown, very **cool**\n we can even link to [stuff](http://google.com)\n```\n\nRenders:\n\n```html\n

    Woah! jade and markdown, very cool we can even link to stuff

    \n```\n\n\n## Code\n\nJade currently supports three classifications of executable code. The first\nis prefixed by `-`, and is not buffered:\n\n```jade\n- var foo = 'bar';\n```\n\nThis can be used for conditionals, or iteration:\n\n```jade\n- for (var key in obj)\n p= obj[key]\n```\n\nDue to Jade's buffering techniques the following is valid as well:\n\n```jade\n- if (foo)\n ul\n li yay\n li foo\n li worked\n- else\n p oh no! didnt work\n```\n\nHell, even verbose iteration:\n\n```jade\n- if (items.length)\n ul\n - items.forEach(function(item){\n li= item\n - })\n```\n\nAnything you want!\n\nNext up we have _escaped_ buffered code, which is used to\nbuffer a return value, which is prefixed by `=`:\n\n```jade\n- var foo = 'bar'\n= foo\nh1= foo\n```\n\nWhich outputs `bar

    bar

    `. Code buffered by `=` is escaped\nby default for security, however to output unescaped return values\nyou may use `!=`:\n\n```jade\np!= aVarContainingMoreHTML\n```\n\n Jade also has designer-friendly variants, making the literal JavaScript\n more expressive and declarative. For example the following assignments\n are equivalent, and the expression is still regular javascript:\n\n```jade\n- var foo = 'foo ' + 'bar'\nfoo = 'foo ' + 'bar'\n```\n\n Likewise Jade has first-class `if`, `else if`, `else`, `until`, `while`, `unless` among others, however you must remember that the expressions are still regular javascript:\n\n```jade\nif foo == 'bar'\n ul\n li yay\n li foo\n li worked\nelse\n p oh no! didnt work\n```\n\n
    \n## Iteration\n\n Along with vanilla JavaScript Jade also supports a subset of\n constructs that allow you to create more designer-friendly templates,\n one of these constructs is `each`, taking the form:\n\n```jade\neach VAL[, KEY] in OBJ\n```\n\nAn example iterating over an array:\n\n```jade\n- var items = [\"one\", \"two\", \"three\"]\neach item in items\n li= item\n```\n\noutputs:\n\n```html\n
  • one
  • \n
  • two
  • \n
  • three
  • \n```\n\niterating an array with index:\n\n```jade\nitems = [\"one\", \"two\", \"three\"]\neach item, i in items\n li #{item}: #{i}\n```\n\noutputs:\n\n```html\n
  • one: 0
  • \n
  • two: 1
  • \n
  • three: 2
  • \n```\n\niterating an object's keys and values:\n\n```jade\nobj = { foo: 'bar' }\neach val, key in obj\n li #{key}: #{val}\n```\n\nwould output `
  • foo: bar
  • `\n\nInternally Jade converts these statements to regular\nJavaScript loops such as `users.forEach(function(user){`,\nso lexical scope and nesting applies as it would with regular\nJavaScript:\n\n```jade\neach user in users\n each role in user.roles\n li= role\n```\n\n You may also use `for` if you prefer:\n\n```jade\nfor user in users\n for role in user.roles\n li= role\n```\n\n
    \n## Conditionals\n\n Jade conditionals are equivalent to those using the code (`-`) prefix,\n however allow you to ditch parenthesis to become more designer friendly,\n however keep in mind the expression given is _regular_ JavaScript:\n\n```jade\nfor user in users\n if user.role == 'admin'\n p #{user.name} is an admin\n else\n p= user.name\n```\n\n is equivalent to the following using vanilla JavaScript literals:\n\n```jade\nfor user in users\n - if (user.role == 'admin')\n p #{user.name} is an admin\n - else\n p= user.name\n```\n\n Jade also provides have `unless` which is equivalent to `if (!(expr))`:\n\n```jade\nfor user in users\n unless user.isAnonymous\n p\n | Click to view\n a(href='/users/' + user.id)= user.name\n```\n\n\n## Template inheritance\n\n Jade supports template inheritance via the `block` and `extends` keywords. A block is simply a \"block\" of Jade that may be replaced within a child template, this process is recursive. To activate template inheritance in Express 2.x you must add: `app.set('view options', { layout: false });`.\n\n Jade blocks can provide default content if desired, however optional as shown below by `block scripts`, `block content`, and `block foot`.\n\n```jade\nhtml\n head\n h1 My Site - #{title}\n block scripts\n script(src='/jquery.js')\n body\n block content\n block foot\n #footer\n p some footer content\n```\n\n Now to extend the layout, simply create a new file and use the `extends` directive as shown below, giving the path (with or without the .jade extension). You may now define one or more blocks that will override the parent block content, note that here the `foot` block is _not_ redefined and will output \"some footer content\".\n\n```jade\nextends layout\n\nblock scripts\n script(src='/jquery.js')\n script(src='/pets.js')\n\nblock content\n h1= title\n each pet in pets\n include pet\n```\n\n It's also possible to override a block to provide additional blocks, as shown in the following example where `content` now exposes a `sidebar` and `primary` block for overriding, or the child template could override `content` all together.\n\n```jade\nextends regular-layout\n\nblock content\n .sidebar\n block sidebar\n p nothing\n .primary\n block primary\n p nothing\n```\n\n\n## Block append / prepend\n\n Jade allows you to _replace_ (default), _prepend_, or _append_ blocks. Suppose for example you have default scripts in a \"head\" block that you wish to utilize on _every_ page, you might do this:\n\n```jade\nhtml\n head\n block head\n script(src='/vendor/jquery.js')\n script(src='/vendor/caustic.js')\n body\n block content\n```\n\n Now suppose you have a page of your application for a JavaScript game, you want some game related scripts as well as these defaults, you can simply `append` the block:\n\n```jade\nextends layout\n\nblock append head\n script(src='/vendor/three.js')\n script(src='/game.js')\n```\n\n When using `block append` or `block prepend` the `block` is optional:\n\n```jade\nextends layout\n\nappend head\n script(src='/vendor/three.js')\n script(src='/game.js')\n```\n\n\n## Includes\n\n Includes allow you to statically include chunks of Jade,\n or other content like css, or html which lives in separate files. The classical example is including a header and footer. Suppose we have the following directory structure:\n\n ./layout.jade\n ./includes/\n ./head.jade\n ./foot.jade\n\nand the following _layout.jade_:\n\n```jade\nhtml\n include includes/head\n body\n h1 My Site\n p Welcome to my super amazing site.\n include includes/foot\n```\n\nboth includes _includes/head_ and _includes/foot_ are\nread relative to the `filename` option given to _layout.jade_,\nwhich should be an absolute path to this file, however Express does this for you. Include then parses these files, and injects the AST produced to render what you would expect:\n\n```html\n\n \n My Site\n \n \n \n

    My Site

    \n

    Welcome to my super lame site.

    \n
    \n

    Copyright>(c) foobar

    \n
    \n \n\n```\n\n As mentioned `include` can be used to include other content\n such as html or css. By providing an extension Jade will not\n assume that the file is Jade source and will include it as\n a literal:\n\n```jade\nhtml\n body\n include content.html\n```\n\n Include directives may also accept a block, in which case the\n the given block will be appended to the _last_ block defined\n in the file. For example if `head.jade` contains:\n\n```jade\nhead\n script(src='/jquery.js')\n```\n\n We may append values by providing a block to `include head`\n as shown below, adding the two scripts.\n\n```jade\nhtml\n include head\n script(src='/foo.js')\n script(src='/bar.js')\n body\n h1 test\n```\n\n You may also `yield` within an included template, allowing you to explicitly mark where the block given to `include` will be placed. Suppose for example you wish to prepend scripts rather than append, you might do the following:\n\n```jade\nhead\n yield\n script(src='/jquery.js')\n script(src='/jquery.ui.js')\n```\n\n Since included Jade is parsed and literally merges the AST, lexically scoped variables function as if the included Jade was written right in the same file. This means `include` may be used as sort of partial, for example suppose we have `user.jade` which utilizes a `user` variable.\n\n```jade\nh1= user.name\np= user.occupation\n```\n\nWe could then simply `include user` while iterating users, and since the `user` variable is already defined within the loop the included template will have access to it.\n\n```jade\nusers = [{ name: 'Tobi', occupation: 'Ferret' }]\n\neach user in users\n .user\n include user\n```\n\nyielding:\n\n```html\n
    \n

    Tobi

    \n

    Ferret

    \n
    \n```\n\nIf we wanted to expose a different variable name as `user` since `user.jade` references that name, we could simply define a new variable as shown here with `user = person`:\n\n```jade\neach person in users\n .user\n user = person\n include user\n```\n\n
    \n## Mixins\n\n Mixins are converted to regular JavaScript functions in\n the compiled template that Jade constructs. Mixins may\n take arguments, though not required:\n\n```jade\nmixin list\n ul\n li foo\n li bar\n li baz\n```\n\n Utilizing a mixin without args looks similar, just without a block:\n\n```jade\nh2 Groceries\nmixin list\n```\n\n Mixins may take one or more arguments as well, the arguments\n are regular javascripts expressions, so for example the following:\n\n```jade\nmixin pets(pets)\n ul.pets\n - each pet in pets\n li= pet\n\nmixin profile(user)\n .user\n h2= user.name\n mixin pets(user.pets)\n```\n\n Would yield something similar to the following html:\n\n```html\n
    \n

    tj

    \n
      \n
    • tobi
    • \n
    • loki
    • \n
    • jane
    • \n
    • manny
    • \n
    \n
    \n```\n\n
    \n## Generated Output\n\n Suppose we have the following Jade:\n\n```jade\n- var title = 'yay'\nh1.title #{title}\np Just an example\n```\n\n When the `compileDebug` option is not explicitly `false`, Jade\n will compile the function instrumented with `__.lineno = n;`, which\n in the event of an exception is passed to `rethrow()` which constructs\n a useful message relative to the initial Jade input.\n\n```js\nfunction anonymous(locals) {\n var __ = { lineno: 1, input: \"- var title = 'yay'\\nh1.title #{title}\\np Just an example\", filename: \"testing/test.js\" };\n var rethrow = jade.rethrow;\n try {\n var attrs = jade.attrs, escape = jade.escape;\n var buf = [];\n with (locals || {}) {\n var interp;\n __.lineno = 1;\n var title = 'yay'\n __.lineno = 2;\n buf.push('');\n buf.push('' + escape((interp = title) == null ? '' : interp) + '');\n buf.push('');\n __.lineno = 3;\n buf.push('

    ');\n buf.push('Just an example');\n buf.push('

    ');\n }\n return buf.join(\"\");\n } catch (err) {\n rethrow(err, __.input, __.filename, __.lineno);\n }\n}\n```\n\nWhen the `compileDebug` option _is_ explicitly `false`, this instrumentation\nis stripped, which is very helpful for light-weight client-side templates. Combining Jade's options with the `./runtime.js` file in this repo allows you\nto toString() compiled templates and avoid running the entire Jade library on\nthe client, increasing performance, and decreasing the amount of JavaScript\nrequired.\n\n```js\nfunction anonymous(locals) {\n var attrs = jade.attrs, escape = jade.escape;\n var buf = [];\n with (locals || {}) {\n var interp;\n var title = 'yay'\n buf.push('');\n buf.push('' + escape((interp = title) == null ? '' : interp) + '');\n buf.push('');\n buf.push('

    ');\n buf.push('Just an example');\n buf.push('

    ');\n }\n return buf.join(\"\");\n}\n```\n\n
    \n## Example Makefile\n\n Below is an example Makefile used to compile _pages/*.jade_\n into _pages/*.html_ files by simply executing `make`.\n\n```make\nJADE = $(shell find pages/*.jade)\nHTML = $(JADE:.jade=.html)\n\nall: $(HTML)\n\n%.html: %.jade\n jade < $< --path $< > $@\n\nclean:\n rm -f $(HTML)\n\n.PHONY: clean\n```\n\nthis can be combined with the `watch(1)` command to produce\na watcher-like behaviour:\n\n```bash\n$ watch make\n```\n\n\n## jade(1)\n\n```\n\nUsage: jade [options] [dir|file ...]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -o, --obj javascript options object\n -O, --out
    output the compiled html to \n -p, --path filename used to resolve includes\n -P, --pretty compile pretty html output\n -c, --client compile for client-side runtime.js\n -D, --no-debug compile without debugging (smaller functions)\n\nExamples:\n\n # translate jade the templates dir\n $ jade templates\n\n # create {foo,bar}.html\n $ jade {foo,bar}.jade\n\n # jade over stdio\n $ jade < my.jade > my.html\n\n # jade over stdio\n $ echo \"h1 Jade!\" | jade\n\n # foo, bar dirs rendering to /tmp\n $ jade foo bar --out /tmp\n\n```\n\n\n## Tutorials\n\n - cssdeck interactive [Jade syntax tutorial](http://cssdeck.com/labs/learning-the-jade-templating-engine-syntax)\n - cssdeck interactive [Jade logic tutorial](http://cssdeck.com/labs/jade-templating-tutorial-codecast-part-2)\n - in [Japanese](http://blog.craftgear.net/4f501e97c1347ec934000001/title/10%E5%88%86%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8Bjade%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3)\n\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "_id": "jade@0.28.1", + "dist": { + "shasum": "39b19c3d637f74aae346ee0b8df6cb3f22f5689f" + }, + "_from": "jade@*" +} diff --git a/node_modules/jade/runtime.js b/node_modules/jade/runtime.js new file mode 100644 index 0000000..0f54907 --- /dev/null +++ b/node_modules/jade/runtime.js @@ -0,0 +1,179 @@ + +jade = (function(exports){ +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Lame Array.isArray() polyfill for now. + */ + +if (!Array.isArray) { + Array.isArray = function(arr){ + return '[object Array]' == Object.prototype.toString.call(arr); + }; +} + +/** + * Lame Object.keys() polyfill for now. + */ + +if (!Object.keys) { + Object.keys = function(obj){ + var arr = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + arr.push(key); + } + } + return arr; + } +} + +/** + * Merge two attribute objects giving precedence + * to values in object `b`. Classes are special-cased + * allowing for arrays and merging/joining appropriately + * resulting in a string. + * + * @param {Object} a + * @param {Object} b + * @return {Object} a + * @api private + */ + +exports.merge = function merge(a, b) { + var ac = a['class']; + var bc = b['class']; + + if (ac || bc) { + ac = ac || []; + bc = bc || []; + if (!Array.isArray(ac)) ac = [ac]; + if (!Array.isArray(bc)) bc = [bc]; + ac = ac.filter(nulls); + bc = bc.filter(nulls); + a['class'] = ac.concat(bc).join(' '); + } + + for (var key in b) { + if (key != 'class') { + a[key] = b[key]; + } + } + + return a; +}; + +/** + * Filter null `val`s. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function nulls(val) { + return val != null; +} + +/** + * Render the given attributes object. + * + * @param {Object} obj + * @param {Object} escaped + * @return {String} + * @api private + */ + +exports.attrs = function attrs(obj, escaped){ + var buf = [] + , terse = obj.terse; + + delete obj.terse; + var keys = Object.keys(obj) + , len = keys.length; + + if (len) { + buf.push(''); + for (var i = 0; i < len; ++i) { + var key = keys[i] + , val = obj[key]; + + if ('boolean' == typeof val || null == val) { + if (val) { + terse + ? buf.push(key) + : buf.push(key + '="' + key + '"'); + } + } else if (0 == key.indexOf('data') && 'string' != typeof val) { + buf.push(key + "='" + JSON.stringify(val) + "'"); + } else if ('class' == key && Array.isArray(val)) { + buf.push(key + '="' + exports.escape(val.join(' ')) + '"'); + } else if (escaped && escaped[key]) { + buf.push(key + '="' + exports.escape(val) + '"'); + } else { + buf.push(key + '="' + val + '"'); + } + } + } + + return buf.join(' '); +}; + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +exports.escape = function escape(html){ + return String(html) + .replace(/&(?!(\w+|\#\d+);)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; + +/** + * Re-throw the given `err` in context to the + * the jade in `filename` at the given `lineno`. + * + * @param {Error} err + * @param {String} filename + * @param {String} lineno + * @api private + */ + +exports.rethrow = function rethrow(err, filename, lineno){ + if (!filename) throw err; + + var context = 3 + , str = require('fs').readFileSync(filename, 'utf8') + , lines = str.split('\n') + , start = Math.max(lineno - context, 0) + , end = Math.min(lines.length, lineno + context); + + // Error context + var context = lines.slice(start, end).map(function(line, i){ + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + + curr + + '| ' + + line; + }).join('\n'); + + // Alter exception message + err.path = filename; + err.message = (filename || 'Jade') + ':' + lineno + + '\n' + context + '\n\n' + err.message; + throw err; +}; + + return exports; + +})({}); diff --git a/node_modules/jade/runtime.min.js b/node_modules/jade/runtime.min.js new file mode 100644 index 0000000..1714efb --- /dev/null +++ b/node_modules/jade/runtime.min.js @@ -0,0 +1 @@ +jade=function(exports){Array.isArray||(Array.isArray=function(arr){return"[object Array]"==Object.prototype.toString.call(arr)}),Object.keys||(Object.keys=function(obj){var arr=[];for(var key in obj)obj.hasOwnProperty(key)&&arr.push(key);return arr}),exports.merge=function merge(a,b){var ac=a["class"],bc=b["class"];if(ac||bc)ac=ac||[],bc=bc||[],Array.isArray(ac)||(ac=[ac]),Array.isArray(bc)||(bc=[bc]),ac=ac.filter(nulls),bc=bc.filter(nulls),a["class"]=ac.concat(bc).join(" ");for(var key in b)key!="class"&&(a[key]=b[key]);return a};function nulls(val){return val!=null}return exports.attrs=function attrs(obj,escaped){var buf=[],terse=obj.terse;delete obj.terse;var keys=Object.keys(obj),len=keys.length;if(len){buf.push("");for(var i=0;i/g,">").replace(/"/g,""")},exports.rethrow=function rethrow(err,filename,lineno){if(!filename)throw err;var context=3,str=require("fs").readFileSync(filename,"utf8"),lines=str.split("\n"),start=Math.max(lineno-context,0),end=Math.min(lines.length,lineno+context),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message,err},exports}({}); \ No newline at end of file diff --git a/node_modules/jade/testing/index.html b/node_modules/jade/testing/index.html new file mode 100644 index 0000000..105c9f4 --- /dev/null +++ b/node_modules/jade/testing/index.html @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/node_modules/jade/testing/index.jade b/node_modules/jade/testing/index.jade new file mode 100644 index 0000000..a22e82a --- /dev/null +++ b/node_modules/jade/testing/index.jade @@ -0,0 +1,4 @@ + +html + body + include some.js diff --git a/node_modules/jade/testing/layout.html b/node_modules/jade/testing/layout.html new file mode 100644 index 0000000..cbbfc7a --- /dev/null +++ b/node_modules/jade/testing/layout.html @@ -0,0 +1 @@ +Application \ No newline at end of file diff --git a/node_modules/jade/testing/layout.jade b/node_modules/jade/testing/layout.jade new file mode 100644 index 0000000..a48765c --- /dev/null +++ b/node_modules/jade/testing/layout.jade @@ -0,0 +1,6 @@ +!!! 5 +html + head + title Application + body + block content diff --git a/node_modules/jade/testing/mobile.html b/node_modules/jade/testing/mobile.html new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/testing/mobile.jade b/node_modules/jade/testing/mobile.jade new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jade/testing/nested/something.html b/node_modules/jade/testing/nested/something.html new file mode 100644 index 0000000..d6b0493 --- /dev/null +++ b/node_modules/jade/testing/nested/something.html @@ -0,0 +1 @@ +

    out

    \ No newline at end of file diff --git a/node_modules/jade/testing/nested/something.jade b/node_modules/jade/testing/nested/something.jade new file mode 100644 index 0000000..552c797 --- /dev/null +++ b/node_modules/jade/testing/nested/something.jade @@ -0,0 +1 @@ +p out \ No newline at end of file diff --git a/node_modules/jade/testing/some.js b/node_modules/jade/testing/some.js new file mode 100644 index 0000000..3104e71 --- /dev/null +++ b/node_modules/jade/testing/some.js @@ -0,0 +1,4 @@ + +if (something) { + something('hey'); +} diff --git a/node_modules/jade/testing/test.md b/node_modules/jade/testing/test.md new file mode 100644 index 0000000..9af1bb2 --- /dev/null +++ b/node_modules/jade/testing/test.md @@ -0,0 +1,5 @@ +Just a _test_ of some **markdown**: + + - foo + - bar + - baz diff --git a/node_modules/jsdom/.travis.yml b/node_modules/jsdom/.travis.yml new file mode 100644 index 0000000..baa0031 --- /dev/null +++ b/node_modules/jsdom/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/jsdom/LICENSE.txt b/node_modules/jsdom/LICENSE.txt new file mode 100644 index 0000000..0dbd429 --- /dev/null +++ b/node_modules/jsdom/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2010 Elijah Insua + +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. diff --git a/node_modules/jsdom/README.md b/node_modules/jsdom/README.md new file mode 100644 index 0000000..314bb14 --- /dev/null +++ b/node_modules/jsdom/README.md @@ -0,0 +1,310 @@ +# jsdom + +A JavaScript implementation of the W3C DOM. + +## Install + +```bash +$ npm install jsdom +``` + +## Human contact + +see: [mailing list](http://groups.google.com/group/jsdom) + +## Easymode + +Bootstrapping a DOM is generally a difficult process involving many error prone steps. We didn't want jsdom to fall into the same trap and that is why a new method, `jsdom.env()`, has been added in jsdom 0.2.0 which should make everyone's lives easier. + +with URL + +```js +// Count all of the links from the nodejs build page +var jsdom = require("jsdom"); + +jsdom.env( + "http://nodejs.org/dist/", + ["http://code.jquery.com/jquery.js"], + function (errors, window) { + console.log("there have been", window.$("a").length, "nodejs releases!"); + } +); +``` + +or with raw HTML + +```js +// Run some jQuery on a html fragment +var jsdom = require("jsdom"); + +jsdom.env( + '

    jsdom\'s Homepage

    ', + ["http://code.jquery.com/jquery.js"], + function(errors, window) { + console.log("contents of a.the-link:", window.$("a.the-link").text()); + } +); +``` + +or with a configuration object + +```js +// Print all of the news items on hackernews +var jsdom = require("jsdom"); + +jsdom.env({ + html: "http://news.ycombinator.com/", + scripts: ["http://code.jquery.com/jquery.js"], + done: function (errors, window) { + var $ = window.$; + console.log("HN Links"); + $("td.title:not(:last) a").each(function() { + console.log(" -", $(this).text()); + }); + } +}); +``` + +or with raw JavaScript source + +```js +// Print all of the news items on hackernews +var jsdom = require("jsdom"); +var fs = require("fs"); +var jquery = fs.readFileSync("./jquery.js").toString(); + +jsdom.env({ + html: "http://news.ycombinator.com/", + src: [jquery], + done: function (errors, window) { + var $ = window.$; + console.log("HN Links"); + $("td.title:not(:last) a").each(function() { + console.log(" -", $(this).text()); + }); + } +}); +``` + +### How it works +`jsdom.env` is built for ease of use, which is rare in the world of the DOM! Since the web has some absolutely horrible JavaScript on it, as of jsdom 0.2.0 `jsdom.env` will not process external resources (scripts, images, etc). If you want to process the JavaScript use one of the methods below (`jsdom.jsdom` or `jsdom.jQueryify`) + +```js +jsdom.env(html, [scripts], [config], callback); +``` + +- `html` (**required**): may be a URL, HTML fragment, or file. +- `scripts` (**optional**): may contain files or URLs. +- `config` (**optional**): see below. +- `callback` (**required**): takes two arguments: + - `errors`: an array of errors + - `window`: a brand new window + +_example:_ + +```js +jsdom.env(html, function (errors, window) { + // free memory associated with the window + window.close(); +}); +``` + +If you would like to specify a configuration object only: + +```js +jsdom.env(config); +``` + +- `config.html`: see `html` above. +- `config.scripts`: see `scripts` above. +- `config.src`: an array of JavaScript strings that will be evaluated against the resulting document. Similar to `scripts`, but it accepts JavaScript instead of paths/URLs. +- `config.done`: see `callback` above. +- `config.document`: + - `referer`: the new document will have this referer + - `cookie`: manually set a cookie value, e.g. `'key=value; expires=Wed, Sep 21 2011 12:00:00 GMT; path=/'` +- `config.features` : see `Flexibility` section below. **Note**: the default feature set for jsdom.env does _not_ include fetching remote JavaScript and executing it. This is something that you will need to **carefully** enable yourself. + +## For the hardcore + +If you want to spawn a document/window and specify all sorts of options this is the section for you. This section covers the `jsdom.jsdom` method: + +```js +var jsdom = require("jsdom").jsdom; +var doc = jsdom(markup, level, options); +var window = doc.createWindow(); +``` + +- `markup` is an HTML/XML document to be parsed. You can also pass `null` or an undefined value to get a basic document with empty `` and `` tags. Document fragments are also supported (including `""`), and will behave as sanely as possible (e.g. the resulting document will lack the `head`, `body` and `documentElement` properties if the corresponding elements aren't included). + +- `level` is `null` (which means level3) by default, but you can pass another level if you'd like. + + ```js + var jsdom = require("jsdom"); + var doc = jsdom.jsdom("", jsdom.level(1, "core")); + ``` + +- `options` see the **Flexibility** section below. + +### Flexibility + +One of the goals of jsdom is to be as minimal and light as possible. This section details how someone can change the behavior of `Document`s on the fly. These features are baked into the `DOMImplementation` that every `Document` has, and may be tweaked in two ways: + +1. When you create a new `Document` using the jsdom builder (`require("jsdom").jsdom()`) + + ```js + var jsdom = require("jsdom").jsdom; + var doc = jsdom("", null, { + features: { + FetchExternalResources : ["img"] + } + }); + ``` + + Do note, that this will only affect the document that is currently being created. All other documents will use the defaults specified below (see: Default Features). + +2. Before creating any documents, you can modify the defaults for all future documents: + + ```js + require("jsdom").defaultDocumentFeatures = { + FetchExternalResources: ["script"], + ProcessExternalResources: false + }; + ``` + +#### Default Features + +Default features are extremely important for jsdom as they lower the configuration requirement and present developers a set of consistent default behaviors. The following sections detail the available features, their defaults, and the values that jsdom uses. + + +`FetchExternalResources` + +- _Default_: `["script"]` +- _Allowed_: `["script", "img", "css", "frame", "iframe", "link"]` or `false` + +Enables/disables fetching files over the file system/HTTP. + +`ProcessExternalResources` + +- _Default_: `["script"]` +- _Allowed_: `["script"]` or `false` + +Disabling this will disable script execution (currently only JavaScript). + +`SkipExternalResources` + +- _Default_: `false` +- _Allowed_: `/url to be skipped/` or `false` +- _Example_: `/http:\/\/example.org/js/bad\.js/` + +Do not download and process resources with url matching a regular expression. + +## Canvas + +jsdom includes support for using the [canvas](https://npmjs.org/package/canvas) package to extend any `` elements with the canvas API. To make this work, you need to include canvas as a dependency in your project, as a peer of jsdom. If jsdom can find the canvas package, it will use it, but if it's not present, then `` elements will behave like `
    `s. + +# More Examples + +## Creating a document-less window + +```js +var jsdom = require("jsdom"); +var window = jsdom.createWindow(); + +console.log(window.document); // output: undefined +``` + +## Creating a document + +```js +var jsdom = require("jsdom"); +var doc = new (jsdom.level(1, "core").Document)(); + +console.log(doc.nodeName); // outputs: #document +``` + +## Creating a browser-like BOM/DOM/Window + +```js +var jsdom = require("jsdom").jsdom; +var document = jsdom("hello world"); +var window = document.createWindow(); + +console.log(window.document.innerHTML); +// output: "hello world" + +console.log(window.innerWidth); +// output: 1024 + +console.log(typeof window.document.getElementsByClassName); +// outputs: function +``` + +## jQueryify + +```js +var jsdom = require("jsdom"); +var window = jsdom.jsdom().createWindow(); + +jsdom.jQueryify(window, "http://code.jquery.com/jquery.js", function () { + window.$("body").append('
    Hello World, It works
    '); + + console.log(window.$(".testing").text()); +}); +``` + +## Passing objects to scripts inside the page + +```js +var jsdom = require("jsdom").jsdom; +var window = jsdom().createWindow(); + +window.__myObject = { foo: "bar" }; + +var scriptEl = window.document.createElement("script"); +scriptEl.src = "anotherScript.js"; +window.document.body.appendChild(scriptEl); + +// anotherScript.js will have the ability to read `window.__myObject`, even +// though it originated in Node! +``` + +# Test Compliance: + +``` + level1/core 532/532 100% + level1/html 238/238 100% + level1/svg 527/527 100% + level2/core 283/283 100% + level2/html 697/697 100% + level2/style 10/10 100% + level2/extra 4/4 100% + level2/events 24/24 100% + level3/xpath 93/93 100% + window/index 5/5 100% + window/script 10/10 100% + window/frame 14/14 100% + sizzle/index 9/14 64% + jsdom/index 86/86 100% + jsonp/jsonp 1/1 100% + browser/contextifyReplacement 4/4 100% + browser/index 22/22 100% +------------------------------------------------------ +TOTALS: 5/2564 failed; 99% success +``` + +## Running the tests + +First you'll want to `npm install`. To run all the tests, use `npm test`, which just calls `node test/runner`. + +Using `test/runner` directly, you can slice and dice which tests your want to run from different levels. Usage is as follows: + +``` +test/runner --help +Run the jsdom test suite + +Options: +-s, --suites suites that you want to run. ie: -s level1/core,1/html,html [string] +-f, --fail-fast stop on the first failed test +-h, --help show the help +-t, --tests choose the test cases to run. ie: -t jquery +``` diff --git a/node_modules/jsdom/lib/jsdom.js b/node_modules/jsdom/lib/jsdom.js new file mode 100644 index 0000000..e6d22fb --- /dev/null +++ b/node_modules/jsdom/lib/jsdom.js @@ -0,0 +1,368 @@ +var dom = exports.dom = require("./jsdom/level3/index").dom, + features = require('./jsdom/browser/documentfeatures'), + fs = require("fs"), + pkg = JSON.parse(fs.readFileSync(__dirname + "/../package.json")), + request = require('request'), + URL = require('url'); + +var style = require('./jsdom/level2/style'); +exports.defaultLevel = dom.level3.html; +exports.browserAugmentation = require("./jsdom/browser/index").browserAugmentation; +exports.windowAugmentation = require("./jsdom/browser/index").windowAugmentation; + +// Proxy feature functions to features module. +['availableDocumentFeatures', + 'defaultDocumentFeatures', + 'applyDocumentFeatures'].forEach(function (propName) { + exports.__defineGetter__(propName, function () { + return features[propName]; + }); + exports.__defineSetter__(propName, function (val) { + return features[propName] = val; + }); +}); + +exports.debugMode = false; + +var createWindow = exports.createWindow = require("./jsdom/browser/index").createWindow; + +exports.__defineGetter__('version', function() { + return pkg.version; +}); + +exports.level = function (level, feature) { + if(!feature) { + feature = 'core'; + } + + return require('./jsdom/level' + level + '/' + feature).dom['level' + level][feature]; +}; + +exports.jsdom = function (html, level, options) { + + options = options || {}; + if(typeof level == "string") { + level = exports.level(level, 'html'); + } else { + level = level || exports.defaultLevel; + } + + if (!options.url) { + options.url = (module.parent.id === 'jsdom') ? + module.parent.parent.filename : + module.parent.filename; + options.url = options.url.replace(/\\/g, '/'); + if (options.url[0] !== '/') { + options.url = '/' + options.url; + } + options.url = 'file://' + options.url; + } + + var browser = exports.browserAugmentation(level, options), + doc = (browser.HTMLDocument) ? + new browser.HTMLDocument(options) : + new browser.Document(options); + + require("./jsdom/selectors/index").applyQuerySelector(doc, level); + + features.applyDocumentFeatures(doc, options.features); + + if (typeof html === 'undefined' || html === null) { + doc.write(''); + } else { + doc.write(html + ''); + } + + if (doc.close && !options.deferClose) { + doc.close(); + } + + // Kept for backwards-compatibility. The window is lazily created when + // document.parentWindow or document.defaultView is accessed. + doc.createWindow = function() { + // Remove ourself + if (doc.createWindow) { + delete doc.createWindow; + } + return doc.parentWindow; + }; + + return doc; +}; + +exports.html = function(html, level, options) { + html += ''; + + // TODO: cache a regex and use it here instead + // or make the parser handle it + var htmlLowered = html.toLowerCase(); + + // body + if (!~htmlLowered.indexOf(''; + } + + // html + if (!~htmlLowered.indexOf(''; + } + return exports.jsdom(html, level, options); +}; + +exports.jQueryify = exports.jsdom.jQueryify = function (window /* path [optional], callback */) { + + if (!window || !window.document) { return; } + + var args = Array.prototype.slice.call(arguments), + callback = (typeof(args[args.length - 1]) === 'function') && args.pop(), + path, + jQueryTag = window.document.createElement("script"); + jQueryTag.className = "jsdom"; + + if (args.length > 1 && typeof(args[1] === 'string')) { + path = args[1]; + } + + var features = window.document.implementation._features; + + window.document.implementation.addFeature('FetchExternalResources', ['script']); + window.document.implementation.addFeature('ProcessExternalResources', ['script']); + window.document.implementation.addFeature('MutationEvents', ["2.0"]); + jQueryTag.src = path || 'http://code.jquery.com/jquery-latest.js'; + window.document.body.appendChild(jQueryTag); + + jQueryTag.onload = function() { + if (callback) { + callback(window, window.jQuery); + } + + window.document.implementation._features = features; + }; + + return window; +}; + + +exports.env = exports.jsdom.env = function() { + var + args = Array.prototype.slice.call(arguments), + config = exports.env.processArguments(args), + callback = config.done, + processHTML = function(err, html) { + + html += ''; + if(err) { + return callback(err); + } + + config.scripts = config.scripts || []; + if (typeof config.scripts === 'string') { + config.scripts = [config.scripts]; + } + + config.src = config.src || []; + if (typeof config.src === 'string') { + config.src = [config.src]; + } + + var + options = { + features: config.features || { + 'FetchExternalResources' : false, + 'ProcessExternalResources' : false, + 'SkipExternalResources' : false + }, + url: config.url + }, + window = exports.html(html, null, options).createWindow(), + features = JSON.parse(JSON.stringify(window.document.implementation._features)), + docsLoaded = 0, + totalDocs = config.scripts.length + config.src.length, + readyState = null, + errors = null; + + if (!window || !window.document) { + return callback(new Error('JSDOM: a window object could not be created.')); + } + + if( config.document ) { + window.document._referrer = config.document.referrer; + window.document._cookie = config.document.cookie; + } + + window.document.implementation.addFeature('FetchExternalResources', ['script']); + window.document.implementation.addFeature('ProcessExternalResources', ['script']); + window.document.implementation.addFeature('MutationEvents', ['2.0']); + + var scriptComplete = function() { + docsLoaded++; + if (docsLoaded >= totalDocs) { + window.document.implementation._features = features; + + if (errors) { + errors = errors.concat(window.document.errors || []); + } + + process.nextTick(function() { callback(errors, window); }); + } + } + + if (config.scripts.length > 0 || config.src.length > 0) { + config.scripts.forEach(function(src) { + var script = window.document.createElement('script'); + script.className = "jsdom"; + script.onload = function() { + scriptComplete() + }; + + script.onerror = function(e) { + if (!errors) { + errors = []; + } + errors.push(e.error); + scriptComplete(); + }; + + script.src = src; + try { + // project against invalid dom + // ex: http://www.google.com/foo#bar + window.document.documentElement.appendChild(script); + } catch(e) { + if(!errors) { + errors=[]; + } + errors.push(e.error || e.message); + scriptComplete(); + } + }); + + config.src.forEach(function(src) { + var script = window.document.createElement('script'); + script.onload = function() { + process.nextTick(scriptComplete); + }; + + script.onerror = function(e) { + if (!errors) { + errors = []; + } + errors.push(e.error || e.message); + // nextTick so that an exception within scriptComplete won't cause + // another script onerror (which would be an infinite loop) + process.nextTick(scriptComplete); + }; + + script.text = src; + window.document.documentElement.appendChild(script); + window.document.documentElement.removeChild(script); + }); + } else { + scriptComplete(); + } + }; + + config.html += ''; + + // Handle markup + if (config.html.indexOf("\n") > 0 || config.html.match(/^\W*)(?=<(?!\/\2))/gi, + singleTag: (function() { + var tags = []; + for (var i in singleTags) { + tags.push(i); + } + return new RegExp('<' + tags.join('|<'), 'i'); + })() +}; + +var uncanon = function(str, letter) { + return '-' + letter.toLowerCase(); +}; + +var HTMLEncode = require('./htmlencoding').HTMLEncode; + +exports.stringifyElement = function stringifyElement(element) { + var tagName = element.tagName.toLowerCase(), + ret = { + start: "<" + tagName, + end:'' + }, + attributes = [], + i, + attribute = null; + + if (element.attributes.length) { + ret.start += " "; + for (i = 0; i"; + } + + return ret; +}; + +var rawTextElements = /SCRIPT|STYLE/i; + +function stringifyDoctype (doctype) { + if (doctype.ownerDocument && doctype.ownerDocument._fullDT) { + return doctype.ownerDocument._fullDT; + } + + var dt = ' -1) { + dt += "'" + doctype.systemId + "'"; + } else { + dt += '"' + doctype.systemId + '"'; + } + } + dt += '>'; + return dt; +} + +exports.makeHtmlGenerator = function makeHtmlGenerator(indentUnit, eol) { + indentUnit = indentUnit || ""; + eol = eol || ""; + + return function generateHtmlRecursive(node, rawText, curIndent) { + var ret = "", parent, current, i; + curIndent = curIndent || ""; + if (node) { + if (node.nodeType && + node.nodeType === node.ENTITY_REFERENCE_NODE) { + node = node._entity; + } + + var childNodesRawText = rawText || rawTextElements.test(node.nodeName); + + switch (node.nodeType) { + case node.ELEMENT_NODE: + current = exports.stringifyElement(node); + if (childNodesRawText) { + ret += curIndent + current.start; + } else { + ret += curIndent + current.start; + } + if (node._childNodes.length > 0) { + if (node._childNodes[0].nodeType !== node.TEXT_NODE) { + ret += eol; + } + for (i=0; i' + eol; + break; + case node.DOCUMENT_NODE: + for (i=0; i', + 'nbsp': ' ', + 'iexcl': '¡', + 'cent': '¢', + 'pound': '£', + 'curren': '¤', + 'yen': '¥', + 'brvbar': '¦', + 'sect': '§', + 'uml': '¨', + 'copy': '©', + 'ordf': 'ª', + 'laquo': '«', + 'not': '¬', + 'shy': '­', + 'reg': '®', + 'macr': '¯', // http://www.w3.org/TR/html4/sgml/entities.html + 'strns': '¯', // http://www.w3.org/TR/html5/named-character-references.html + 'deg': '°', + 'plusmn': '±', // http://www.w3.org/TR/html4/sgml/entities.html + 'pm': '±', // http://www.w3.org/TR/html5/named-character-references.html + 'sup2': '²', + 'sup3': '³', + 'acute': '´', + 'micro': 'µ', + 'para': '¶', + 'middot': '·', + 'cedil': '¸', + 'sup1': '¹', + 'ordm': 'º', + 'raquo': '»', + 'frac14': '¼', + 'half': '½', // http://www.w3.org/TR/html4/sgml/entities.html + 'frac12': '½', // http://www.w3.org/TR/html5/named-character-references.html + 'frac34': '¾', + 'iquest': '¿', + 'Agrave': 'À', + 'Aacute': 'Á', + 'Acirc': 'Â', + 'Atilde': 'Ã', + 'Auml': 'Ä', + 'Aring': 'Å', // http://www.w3.org/TR/html4/sgml/entities.html + 'angst': 'Å', // http://www.w3.org/TR/html5/named-character-references.html + 'AElig': 'Æ', + 'Ccedil': 'Ç', + 'Egrave': 'È', + 'Eacute': 'É', + 'Ecirc': 'Ê', + 'Euml': 'Ë', + 'Igrave': 'Ì', + 'Iacute': 'Í', + 'Icirc': 'Î', + 'Iuml': 'Ï', + 'ETH': 'Ð', + 'Ntilde': 'Ñ', + 'Ograve': 'Ò', + 'Oacute': 'Ó', + 'Ocirc': 'Ô', + 'Otilde': 'Õ', + 'Ouml': 'Ö', + 'times': '×', + 'Oslash': 'Ø', + 'Ugrave': 'Ù', + 'Uacute': 'Ú', + 'Ucirc': 'Û', + 'Uuml': 'Ü', + 'Yacute': 'Ý', + 'THORN': 'Þ', + 'szlig': 'ß', + 'agrave': 'à', + 'aacute': 'á', + 'acirc': 'â', + 'atilde': 'ã', + 'auml': 'ä', + 'aring': 'å', + 'aelig': 'æ', + 'ccedil': 'ç', + 'egrave': 'è', + 'eacute': 'é', + 'ecirc': 'ê', + 'euml': 'ë', + 'igrave': 'ì', + 'iacute': 'í', + 'icirc': 'î', + 'iuml': 'ï', + 'eth': 'ð', + 'ntilde': 'ñ', + 'ograve': 'ò', + 'oacute': 'ó', + 'ocirc': 'ô', + 'otilde': 'õ', + 'ouml': 'ö', + 'divide': '÷', + 'oslash': 'ø', + 'ugrave': 'ù', + 'uacute': 'ú', + 'ucirc': 'û', + 'uuml': 'ü', + 'yacute': 'ý', + 'thorn': 'þ', + 'yuml': 'ÿ', + 'Amacr': 'Ā', + 'amacr': 'ā', + 'Abreve': 'Ă', + 'abreve': 'ă', + 'Aogon': 'Ą', + 'aogon': 'ą', + 'Cacute': 'Ć', + 'cacute': 'ć', + 'Ccirc': 'Ĉ', + 'ccirc': 'ĉ', + 'Cdot': 'Ċ', + 'cdot': 'ċ', + 'Ccaron': 'Č', + 'ccaron': 'č', + 'Dcaron': 'Ď', + 'dcaron': 'ď', + 'Dstrok': 'Đ', + 'dstrok': 'đ', + 'Emacr': 'Ē', + 'emacr': 'ē', + 'Edot': 'Ė', + 'edot': 'ė', + 'Eogon': 'Ę', + 'eogon': 'ę', + 'Ecaron': 'Ě', + 'ecaron': 'ě', + 'Gcirc': 'Ĝ', + 'gcirc': 'ĝ', + 'Gbreve': 'Ğ', + 'gbreve': 'ğ', + 'Gdot': 'Ġ', + 'gdot': 'ġ', + 'Gcedil': 'Ģ', + 'Hcirc': 'Ĥ', + 'hcirc': 'ĥ', + 'Hstrok': 'Ħ', + 'hstrok': 'ħ', + 'Itilde': 'Ĩ', + 'itilde': 'ĩ', + 'Imacr': 'Ī', + 'imacr': 'ī', + 'Iogon': 'Į', + 'iogon': 'į', + 'Idot': 'İ', + 'inodot': 'ı', + 'IJlig': 'IJ', + 'ijlig': 'ij', + 'Jcirc': 'Ĵ', + 'jcirc': 'ĵ', + 'Kcedil': 'Ķ', + 'kcedil': 'ķ', + 'kgreen': 'ĸ', + 'Lacute': 'Ĺ', + 'lacute': 'ĺ', + 'Lcedil': 'Ļ', + 'lcedil': 'ļ', + 'Lcaron': 'Ľ', + 'lcaron': 'ľ', + 'Lmidot': 'Ŀ', + 'lmidot': 'ŀ', + 'Lstrok': 'Ł', + 'lstrok': 'ł', + 'Nacute': 'Ń', + 'nacute': 'ń', + 'Ncedil': 'Ņ', + 'ncedil': 'ņ', + 'Ncaron': 'Ň', + 'ncaron': 'ň', + 'napos': 'ʼn', + 'ENG': 'Ŋ', + 'eng': 'ŋ', + 'Omacr': 'Ō', + 'omacr': 'ō', + 'Odblac': 'Ő', + 'odblac': 'ő', + 'OElig': 'Œ', + 'oelig': 'œ', + 'Racute': 'Ŕ', + 'racute': 'ŕ', + 'Rcedil': 'Ŗ', + 'rcedil': 'ŗ', + 'Rcaron': 'Ř', + 'rcaron': 'ř', + 'Sacute': 'Ś', + 'sacute': 'ś', + 'Scirc': 'Ŝ', + 'scirc': 'ŝ', + 'Scedil': 'Ş', + 'scedil': 'ş', + 'Scaron': 'Š', + 'scaron': 'š', + 'Tcedil': 'Ţ', + 'tcedil': 'ţ', + 'Tcaron': 'Ť', + 'tcaron': 'ť', + 'Tstrok': 'Ŧ', + 'tstrok': 'ŧ', + 'Utilde': 'Ũ', + 'utilde': 'ũ', + 'Umacr': 'Ū', + 'umacr': 'ū', + 'Ubreve': 'Ŭ', + 'ubreve': 'ŭ', + 'Uring': 'Ů', + 'uring': 'ů', + 'Udblac': 'Ű', + 'udblac': 'ű', + 'Uogon': 'Ų', + 'uogon': 'ų', + 'Wcirc': 'Ŵ', + 'wcirc': 'ŵ', + 'Ycirc': 'Ŷ', + 'ycirc': 'ŷ', + 'Yuml': 'Ÿ', + 'Zacute': 'Ź', + 'zacute': 'ź', + 'Zdot': 'Ż', + 'zdot': 'ż', + 'Zcaron': 'Ž', + 'zcaron': 'ž', + 'fnof': 'ƒ', + 'imped': 'Ƶ', + 'gacute': 'ǵ', + 'jmath': 'ȷ', + 'circ': 'ˆ', + 'caron': 'ˇ', + 'breve': '˘', + 'dot': '˙', + 'ring': '˚', + 'ogon': '˛', + 'tilde': '˜', + 'dblac': '˝', + 'Alpha': 'Α', + 'Beta': 'Β', + 'Gamma': 'Γ', + 'Delta': 'Δ', + 'Epsilon': 'Ε', + 'Zeta': 'Ζ', + 'Eta': 'Η', + 'Theta': 'Θ', + 'Iota': 'Ι', + 'Kappa': 'Κ', + 'Lambda': 'Λ', + 'Mu': 'Μ', + 'Nu': 'Ν', + 'Xi': 'Ξ', + 'Omicron': 'Ο', + 'Pi': 'Π', + 'Rho': 'Ρ', + 'Sigma': 'Σ', + 'Tau': 'Τ', + 'Upsilon': 'Υ', + 'Phi': 'Φ', + 'Chi': 'Χ', + 'Psi': 'Ψ', + 'Omega': 'Ω', // http://www.w3.org/TR/html4/sgml/entities.html + 'ohm': 'Ω', // http://www.w3.org/TR/html5/named-character-references.html + 'alpha': 'α', + 'beta': 'β', + 'gamma': 'γ', + 'delta': 'δ', + 'epsilon': 'ε', + 'zeta': 'ζ', + 'eta': 'η', + 'theta': 'θ', + 'iota': 'ι', + 'kappa': 'κ', + 'lambda': 'λ', + 'mu': 'μ', + 'nu': 'ν', + 'xi': 'ξ', + 'omicron': 'ο', + 'pi': 'π', + 'rho': 'ρ', + 'sigmaf': 'ς', // http://www.w3.org/TR/html4/sgml/entities.html + 'varsigma': 'ς', // http://www.w3.org/TR/html5/named-character-references.html + 'sigma': 'σ', + 'tau': 'τ', + 'upsilon': 'υ', + 'phi': 'φ', + 'chi': 'χ', + 'psi': 'ψ', + 'omega': 'ω', + 'thetasym': 'ϑ', // http://www.w3.org/TR/html4/sgml/entities.html + 'vartheta': 'ϑ', // http://www.w3.org/TR/html5/named-character-references.html + 'upsih': 'ϒ', + 'varphi': 'ϕ', + 'piv': 'ϖ', // http://www.w3.org/TR/html4/sgml/entities.html + 'varpi': 'ϖ', // http://www.w3.org/TR/html5/named-character-references.html + 'Gammad': 'Ϝ', + 'gammad': 'ϝ', + 'varkappa': 'ϰ', + 'varrho': 'ϱ', + 'varepsilon': 'ϵ', + 'bepsi': '϶', + 'IOcy': 'Ё', + 'DJcy': 'Ђ', + 'GJcy': 'Ѓ', + 'Jukcy': 'Є', + 'DScy': 'Ѕ', + 'Iukcy': 'І', + 'YIcy': 'Ї', + 'Jsercy': 'Ј', + 'LJcy': 'Љ', + 'NJcy': 'Њ', + 'TSHcy': 'Ћ', + 'KJcy': 'Ќ', + 'Ubrcy': 'Ў', + 'DZcy': 'Џ', + 'Acy': 'А', + 'Bcy': 'Б', + 'Vcy': 'В', + 'Gcy': 'Г', + 'Dcy': 'Д', + 'IEcy': 'Е', + 'ZHcy': 'Ж', + 'Zcy': 'З', + 'Icy': 'И', + 'Jcy': 'Й', + 'Kcy': 'К', + 'Lcy': 'Л', + 'Mcy': 'М', + 'Ncy': 'Н', + 'Ocy': 'О', + 'Pcy': 'П', + 'Rcy': 'Р', + 'Scy': 'С', + 'Tcy': 'Т', + 'Ucy': 'У', + 'Fcy': 'Ф', + 'KHcy': 'Х', + 'TScy': 'Ц', + 'CHcy': 'Ч', + 'SHcy': 'Ш', + 'SHCHcy': 'Щ', + 'HARDcy': 'Ъ', + 'Ycy': 'Ы', + 'SOFTcy': 'Ь', + 'Ecy': 'Э', + 'YUcy': 'Ю', + 'YAcy': 'Я', + 'acy': 'а', + 'bcy': 'б', + 'vcy': 'в', + 'gcy': 'г', + 'dcy': 'д', + 'iecy': 'е', + 'zhcy': 'ж', + 'zcy': 'з', + 'icy': 'и', + 'jcy': 'й', + 'kcy': 'к', + 'lcy': 'л', + 'mcy': 'м', + 'ncy': 'н', + 'ocy': 'о', + 'pcy': 'п', + 'rcy': 'р', + 'scy': 'с', + 'tcy': 'т', + 'ucy': 'у', + 'fcy': 'ф', + 'khcy': 'х', + 'tscy': 'ц', + 'chcy': 'ч', + 'shcy': 'ш', + 'shchcy': 'щ', + 'hardcy': 'ъ', + 'ycy': 'ы', + 'softcy': 'ь', + 'ecy': 'э', + 'yucy': 'ю', + 'yacy': 'я', + 'iocy': 'ё', + 'djcy': 'ђ', + 'gjcy': 'ѓ', + 'jukcy': 'є', + 'dscy': 'ѕ', + 'iukcy': 'і', + 'yicy': 'ї', + 'jsercy': 'ј', + 'ljcy': 'љ', + 'njcy': 'њ', + 'tshcy': 'ћ', + 'kjcy': 'ќ', + 'ubrcy': 'ў', + 'dzcy': 'џ', + 'ensp': ' ', + 'emsp': ' ', + 'emsp13': ' ', + 'emsp14': ' ', + 'numsp': ' ', + 'puncsp': ' ', + 'thinsp': ' ', + 'hairsp': ' ', + 'ZeroWidthSpace': '​', + 'zwnj': '‌', + 'zwj': '‍', + 'lrm': '‎', + 'rlm': '‏', + 'hyphen': '‐', + 'ndash': '–', + 'mdash': '—', + 'horbar': '―', + 'Vert': '‖', + 'lsquo': '‘', + 'rsquo': '’', // http://www.w3.org/TR/html4/sgml/entities.html + 'rsquor': '’', // http://www.w3.org/TR/html5/named-character-references.html + 'sbquo': '‚', + 'ldquo': '“', + 'rdquo': '”', // http://www.w3.org/TR/html4/sgml/entities.html + 'rdquor': '”', // http://www.w3.org/TR/html5/named-character-references.html + 'ldquo': '“', // http://www.w3.org/TR/html4/sgml/entities.html + 'ldquor': '„', // http://www.w3.org/TR/html5/named-character-references.html + 'dagger': '†', + 'Dagger': '‡', // http://www.w3.org/TR/html4/sgml/entities.html + 'ddagger': '‡', // http://www.w3.org/TR/html5/named-character-references.html + 'bull': '•', // http://www.w3.org/TR/html4/sgml/entities.html + 'bullet': '•', // http://www.w3.org/TR/html5/named-character-references.html + 'nldr': '‥', + 'hellip': '…', // http://www.w3.org/TR/html4/sgml/entities.html + 'mldr': '…', // http://www.w3.org/TR/html5/named-character-references.html + 'permil': '‰', + 'pertenk': '‱', + 'prime': '′', + 'Prime': '″', + 'tprime': '‴', + 'bprime': '‵', + 'lsaquo': '‹', + 'rsaquo': '›', + 'oline': '‾', + 'caret': '⁁', + 'hybull': '⁃', + 'frasl': '⁄', + 'bsemi': '⁏', + 'qprime': '⁗', + 'MediumSpace': ' ', + 'NoBreak': '⁠', + 'af': '⁡', + 'it': '⁢', + 'ic': '⁣', + 'euro': '€', + 'complexes': 'ℂ', + 'incare': '℅', + 'gscr': 'ℊ', + 'hamilt': 'ℋ', + 'Poincareplane': 'ℌ', + 'quaternions': 'ℍ', + 'planckh': 'ℎ', + 'plankv': 'ℏ', + 'imagline': 'ℐ', + 'image': 'ℑ', // http://www.w3.org/TR/html4/sgml/entities.html + 'imagpart': 'ℑ', // http://www.w3.org/TR/html5/named-character-references.html + 'lagran': 'ℒ', + 'ell': 'ℓ', + 'naturals': 'ℕ', + 'numero': '№', + 'copysr': '℗', + 'weierp': '℘', // http://www.w3.org/TR/html4/sgml/entities.html + 'wp': '℘', // http://www.w3.org/TR/html5/named-character-references.html + 'primes': 'ℙ', + 'rationals': 'ℚ', + 'realine': 'ℛ', + 'real': 'ℜ', // http://www.w3.org/TR/html4/sgml/entities.html + 'realpart': 'ℜ', // http://www.w3.org/TR/html5/named-character-references.html + 'reals': 'ℝ', + 'rx': '℞', + 'trade': '™', + 'integers': 'ℤ', + 'mho': '℧', + 'zeetrf': 'ℨ', + 'iiota': '℩', + 'bernou': 'ℬ', + 'Cfr': 'ℭ', + 'escr': 'ℯ', + 'expectation': 'ℰ', + 'Fscr': 'ℱ', + 'phmmat': 'ℳ', + 'oscr': 'ℴ', + 'alefsym': 'ℵ', // http://www.w3.org/TR/html4/sgml/entities.html + 'aleph': 'ℵ', // http://www.w3.org/TR/html5/named-character-references.html + 'beth': 'ℶ', + 'gimel': 'ℷ', + 'daleth': 'ℸ', + 'DD': 'ⅅ', + 'dd': 'ⅆ', + 'exponentiale': 'ⅇ', + 'ii': 'ⅈ', + 'frac13': '⅓', + 'frac23': '⅔', + 'frac15': '⅕', + 'frac25': '⅖', + 'frac35': '⅗', + 'frac45': '⅘', + 'frac16': '⅙', + 'frac56': '⅚', + 'frac18': '⅛', + 'frac38': '⅜', + 'frac58': '⅝', + 'frac78': '⅞', + 'larr': '←', // http://www.w3.org/TR/html4/sgml/entities.html + 'slarr': '←', // http://www.w3.org/TR/html5/named-character-references.html + 'uarr': '↑', // http://www.w3.org/TR/html4/sgml/entities.html + 'uparrow': '↑', // http://www.w3.org/TR/html5/named-character-references.html + 'rarr': '→', // http://www.w3.org/TR/html4/sgml/entities.html + 'srarr': '→', // http://www.w3.org/TR/html5/named-character-references.html + 'darr': '↓', // http://www.w3.org/TR/html4/sgml/entities.html + 'downarrow': '↓', // http://www.w3.org/TR/html5/named-character-references.html + 'harr': '↔', // http://www.w3.org/TR/html4/sgml/entities.html + 'leftrightarrow': '↔', // http://www.w3.org/TR/html5/named-character-references.html + 'varr': '↕', + 'nwarrow': '↖', + 'nearrow': '↗', + 'searrow': '↘', + 'swarrow': '↙', + 'nleftarrow': '↚', + 'nrightarrow': '↛', + 'rightsquigarrow': '↝', + 'twoheadleftarrow': '↞', + 'Uarr': '↟', + 'twoheadrightarrow': '↠', + 'Darr': '↡', + 'leftarrowtail': '↢', + 'rightarrowtail': '↣', + 'mapstoleft': '↤', + 'mapstoup': '↥', + 'mapsto': '↦', + 'mapstodown': '↧', + 'larrhk': '↩', + 'rarrhk': '↪', + 'looparrowleft': '↫', + 'rarrlp': '↬', + 'leftrightsquigarrow': '↭', + 'nleftrightarrow': '↮', + 'lsh': '↰', + 'rsh': '↱', + 'ldsh': '↲', + 'rdsh': '↳', + 'crarr': '↵', + 'curvearrowleft': '↶', + 'curvearrowright': '↷', + 'olarr': '↺', + 'orarr': '↻', + 'lharu': '↼', + 'lhard': '↽', + 'upharpoonright': '↾', + 'upharpoonleft': '↿', + 'rightharpoonup': '⇀', + 'rightharpoondown': '⇁', + 'downharpoonright': '⇂', + 'downharpoonleft': '⇃', + 'rlarr': '⇄', + 'udarr': '⇅', + 'lrarr': '⇆', + 'llarr': '⇇', + 'uuarr': '⇈', + 'rrarr': '⇉', + 'downdownarrows': '⇊', + 'lrhar': '⇋', + 'rlhar': '⇌', + 'nlArr': '⇍', + 'nhArr': '⇎', + 'nrArr': '⇏', + 'lArr': '⇐', + 'uArr': '⇑', + 'rArr': '⇒', + 'dArr': '⇓', + 'hArr': '⇔', // http://www.w3.org/TR/html4/sgml/entities.html + 'iff': '⇔', // http://www.w3.org/TR/html5/named-character-references.html + 'vArr': '⇕', + 'nwArr': '⇖', + 'neArr': '⇗', + 'seArr': '⇘', + 'swArr': '⇙', + 'lAarr': '⇚', + 'rAarr': '⇛', + 'zigrarr': '⇝', + 'larrb': '⇤', + 'rarrb': '⇥', + 'duarr': '⇵', + 'loarr': '⇽', + 'roarr': '⇾', + 'hoarr': '⇿', + 'forall': '∀', + 'complement': '∁', + 'part': '∂', + 'exist': '∃', + 'nexists': '∄', + 'empty': '∅', // http://www.w3.org/TR/html4/sgml/entities.html + 'varnothing': '∅', // http://www.w3.org/TR/html5/named-character-references.html + 'nabla': '∇', + 'isin': '∈', // http://www.w3.org/TR/html4/sgml/entities.html + 'isinv': '∈', // http://www.w3.org/TR/html5/named-character-references.html + 'notin': '∉', // http://www.w3.org/TR/html4/sgml/entities.html + 'notinva': '∉', // http://www.w3.org/TR/html5/named-character-references.html + 'ni': '∋', // http://www.w3.org/TR/html4/sgml/entities.html + 'niv': '∋', // http://www.w3.org/TR/html5/named-character-references.html + 'notniva': '∌', + 'prod': '∏', + 'coprod': '∐', + 'sum': '∑', + 'minus': '−', + 'mp': '∓', + 'plusdo': '∔', + 'ssetmn': '∖', + 'lowast': '∗', + 'compfn': '∘', + 'radic': '√', + 'prop': '∝', // http://www.w3.org/TR/html4/sgml/entities.html + 'vprop': '∝', // http://www.w3.org/TR/html5/named-character-references.html + 'infin': '∞', + 'angrt': '∟', + 'ang': '∠', // http://www.w3.org/TR/html4/sgml/entities.html + 'angle': '∠', // http://www.w3.org/TR/html5/named-character-references.html + 'measuredangle': '∡', + 'angsph': '∢', + 'smid': '∣', + 'nsmid': '∤', + 'spar': '∥', + 'nspar': '∦', + 'and': '∧', // http://www.w3.org/TR/html4/sgml/entities.html + 'wedge': '∧', // http://www.w3.org/TR/html5/named-character-references.html + 'or': '∨', // http://www.w3.org/TR/html4/sgml/entities.html + 'vee': '∨', // http://www.w3.org/TR/html5/named-character-references.html + 'cap': '∩', + 'cup': '∪', + 'int': '∫', + 'Int': '∬', + 'tint': '∭', + 'oint': '∮', + 'DoubleContourIntegral': '∯', + 'Cconint': '∰', + 'cwint': '∱', + 'cwconint': '∲', + 'awconint': '∳', + 'there4': '∴', // http://www.w3.org/TR/html4/sgml/entities.html + 'therefore': '∴', // http://www.w3.org/TR/html5/named-character-references.html + 'because': '∵', + 'ratio': '∶', + 'Proportion': '∷', + 'minusd': '∸', + 'mDDot': '∺', + 'homtht': '∻', + 'sim': '∼', // http://www.w3.org/TR/html4/sgml/entities.html + 'thksim': '∼', // http://www.w3.org/TR/html5/named-character-references.html + 'bsim': '∽', + 'mstpos': '∾', + 'acd': '∿', + 'wreath': '≀', + 'nsim': '≁', + 'esim': '≂', + 'simeq': '≃', + 'nsimeq': '≄', + 'cong': '≅', + 'simne': '≆', + 'ncong': '≇', + 'asymp': '≈', // http://www.w3.org/TR/html4/sgml/entities.html + 'thkap': '≈', // http://www.w3.org/TR/html5/named-character-references.html + 'napprox': '≉', + 'approxeq': '≊', + 'apid': '≋', + 'bcong': '≌', + 'asympeq': '≍', + 'bump': '≎', + 'bumpeq': '≏', + 'esdot': '≐', + 'eDot': '≑', + 'fallingdotseq': '≒', + 'risingdotseq': '≓', + 'coloneq': '≔', + 'eqcolon': '≕', + 'eqcirc': '≖', + 'cire': '≗', + 'wedgeq': '≙', + 'veeeq': '≚', + 'trie': '≜', + 'questeq': '≟', + 'ne': '≠', + 'equiv': '≡', + 'nequiv': '≢', + 'le': '≤', // http://www.w3.org/TR/html4/sgml/entities.html + 'leq': '≤', // http://www.w3.org/TR/html5/named-character-references.html + 'ge': '≥', // http://www.w3.org/TR/html4/sgml/entities.html + 'geq': '≥', // http://www.w3.org/TR/html5/named-character-references.html + 'leqq': '≦', + 'geqq': '≧', + 'lneqq': '≨', + 'gneqq': '≩', + 'll': '≪', + 'gg': '≫', + 'twixt': '≬', + 'NotCupCap': '≭', + 'nlt': '≮', + 'ngtr': '≯', + 'nleq': '≰', + 'ngeq': '≱', + 'lsim': '≲', + 'gtrsim': '≳', + 'nlsim': '≴', + 'ngsim': '≵', + 'lg': '≶', + 'gtrless': '≷', + 'ntlg': '≸', + 'ntgl': '≹', + 'prec': '≺', + 'succ': '≻', + 'preccurlyeq': '≼', + 'succcurlyeq': '≽', + 'prsim': '≾', + 'succsim': '≿', + 'nprec': '⊀', + 'nsucc': '⊁', + 'sub': '⊂', // http://www.w3.org/TR/html4/sgml/entities.html + 'subset': '⊂', // http://www.w3.org/TR/html5/named-character-references.html + 'sup': '⊃', // http://www.w3.org/TR/html4/sgml/entities.html + 'supset': '⊃', // http://www.w3.org/TR/html5/named-character-references.html + 'nsub': '⊄', + 'nsup': '⊅', + 'sube': '⊆', // http://www.w3.org/TR/html4/sgml/entities.html + 'subseteq': '⊆', // http://www.w3.org/TR/html5/named-character-references.html + 'supe': '⊇', // http://www.w3.org/TR/html4/sgml/entities.html + 'supseteq': '⊇', // http://www.w3.org/TR/html5/named-character-references.html + 'nsubseteq': '⊈', + 'nsupseteq': '⊉', + 'subsetneq': '⊊', + 'supsetneq': '⊋', + 'cupdot': '⊍', + 'uplus': '⊎', + 'sqsubset': '⊏', + 'sqsupset': '⊐', + 'sqsubseteq': '⊑', + 'sqsupseteq': '⊒', + 'sqcap': '⊓', + 'sqcup': '⊔', + 'oplus': '⊕', + 'ominus': '⊖', + 'otimes': '⊗', + 'osol': '⊘', + 'odot': '⊙', + 'ocir': '⊚', + 'oast': '⊛', + 'odash': '⊝', + 'plusb': '⊞', + 'minusb': '⊟', + 'timesb': '⊠', + 'sdotb': '⊡', + 'vdash': '⊢', + 'dashv': '⊣', + 'top': '⊤', + 'perp': '⊥', + 'models': '⊧', + 'vDash': '⊨', + 'Vdash': '⊩', + 'Vvdash': '⊪', + 'VDash': '⊫', + 'nvdash': '⊬', + 'nvDash': '⊭', + 'nVdash': '⊮', + 'nVDash': '⊯', + 'prurel': '⊰', + 'vltri': '⊲', + 'vrtri': '⊳', + 'trianglelefteq': '⊴', + 'trianglerighteq': '⊵', + 'origof': '⊶', + 'imof': '⊷', + 'mumap': '⊸', + 'hercon': '⊹', + 'intercal': '⊺', + 'veebar': '⊻', + 'barvee': '⊽', + 'angrtvb': '⊾', + 'lrtri': '⊿', + 'xwedge': '⋀', + 'xvee': '⋁', + 'xcap': '⋂', + 'xcup': '⋃', + 'diamond': '⋄', + 'sdot': '⋅', + 'sstarf': '⋆', + 'divonx': '⋇', + 'bowtie': '⋈', + 'ltimes': '⋉', + 'rtimes': '⋊', + 'lthree': '⋋', + 'rthree': '⋌', + 'bsime': '⋍', + 'cuvee': '⋎', + 'cuwed': '⋏', + 'Subset': '⋐', + 'Supset': '⋑', + 'Cap': '⋒', + 'Cup': '⋓', + 'pitchfork': '⋔', + 'epar': '⋕', + 'ltdot': '⋖', + 'gtrdot': '⋗', + 'Ll': '⋘', + 'ggg': '⋙', + 'lesseqgtr': '⋚', + 'gtreqless': '⋛', + 'curlyeqprec': '⋞', + 'curlyeqsucc': '⋟', + 'nprcue': '⋠', + 'nsccue': '⋡', + 'nsqsube': '⋢', + 'nsqsupe': '⋣', + 'lnsim': '⋦', + 'gnsim': '⋧', + 'prnsim': '⋨', + 'succnsim': '⋩', + 'ntriangleleft': '⋪', + 'ntriangleright': '⋫', + 'ntrianglelefteq': '⋬', + 'ntrianglerighteq': '⋭', + 'vellip': '⋮', + 'ctdot': '⋯', + 'utdot': '⋰', + 'dtdot': '⋱', + 'disin': '⋲', + 'isinsv': '⋳', + 'isins': '⋴', + 'isindot': '⋵', + 'notinvc': '⋶', + 'notinvb': '⋷', + 'isinE': '⋹', + 'nisd': '⋺', + 'xnis': '⋻', + 'nis': '⋼', + 'notnivc': '⋽', + 'notnivb': '⋾', + 'barwedge': '⌅', + 'doublebarwedge': '⌆', + 'lceil': '⌈', + 'rceil': '⌉', + 'lfloor': '⌊', + 'rfloor': '⌋', + 'drcrop': '⌌', + 'dlcrop': '⌍', + 'urcrop': '⌎', + 'ulcrop': '⌏', + 'bnot': '⌐', + 'profline': '⌒', + 'profsurf': '⌓', + 'telrec': '⌕', + 'target': '⌖', + 'ulcorner': '⌜', + 'urcorner': '⌝', + 'llcorner': '⌞', + 'lrcorner': '⌟', + 'sfrown': '⌢', + 'ssmile': '⌣', + 'lang': '〈', // http://www.w3.org/TR/html4/sgml/entities.html + 'rang': '〉', // http://www.w3.org/TR/html4/sgml/entities.html + 'cylcty': '⌭', + 'profalar': '⌮', + 'topbot': '⌶', + 'ovbar': '⌽', + 'solbar': '⌿', + 'angzarr': '⍼', + 'lmoustache': '⎰', + 'rmoustache': '⎱', + 'tbrk': '⎴', + 'bbrk': '⎵', + 'bbrktbrk': '⎶', + 'OverParenthesis': '⏜', + 'UnderParenthesis': '⏝', + 'OverBrace': '⏞', + 'UnderBrace': '⏟', + 'trpezium': '⏢', + 'elinters': '⏧', + 'blank': '␣', + 'oS': 'Ⓢ', + 'boxh': '─', + 'boxv': '│', + 'boxdr': '┌', + 'boxdl': '┐', + 'boxur': '└', + 'boxul': '┘', + 'boxvr': '├', + 'boxvl': '┤', + 'boxhd': '┬', + 'boxhu': '┴', + 'boxvh': '┼', + 'boxH': '═', + 'boxV': '║', + 'boxdR': '╒', + 'boxDr': '╓', + 'boxDR': '╔', + 'boxdL': '╕', + 'boxDl': '╖', + 'boxDL': '╗', + 'boxuR': '╘', + 'boxUr': '╙', + 'boxUR': '╚', + 'boxuL': '╛', + 'boxUl': '╜', + 'boxUL': '╝', + 'boxvR': '╞', + 'boxVr': '╟', + 'boxVR': '╠', + 'boxvL': '╡', + 'boxVl': '╢', + 'boxVL': '╣', + 'boxHd': '╤', + 'boxhD': '╥', + 'boxHD': '╦', + 'boxHu': '╧', + 'boxhU': '╨', + 'boxHU': '╩', + 'boxvH': '╪', + 'boxVh': '╫', + 'boxVH': '╬', + 'uhblk': '▀', + 'lhblk': '▄', + 'block': '█', + 'blk14': '░', + 'blk12': '▒', + 'blk34': '▓', + 'square': '□', + 'squf': '▪', + 'EmptyVerySmallSquare': '▫', + 'rect': '▭', + 'marker': '▮', + 'fltns': '▱', + 'xutri': '△', + 'utrif': '▴', + 'utri': '▵', + 'rtrif': '▸', + 'triangleright': '▹', + 'xdtri': '▽', + 'dtrif': '▾', + 'triangledown': '▿', + 'ltrif': '◂', + 'triangleleft': '◃', + 'loz': '◊', // http://www.w3.org/TR/html4/sgml/entities.html + 'lozenge': '◊', // http://www.w3.org/TR/html5/named-character-references.html + 'cir': '○', + 'tridot': '◬', + 'xcirc': '◯', + 'ultri': '◸', + 'urtri': '◹', + 'lltri': '◺', + 'EmptySmallSquare': '◻', + 'FilledSmallSquare': '◼', + 'starf': '★', + 'star': '☆', + 'phone': '☎', + 'female': '♀', + 'male': '♂', + 'spades': '♠', // http://www.w3.org/TR/html4/sgml/entities.html + 'spadesuit': '♠', // http://www.w3.org/TR/html5/named-character-references.html + 'clubs': '♣', // http://www.w3.org/TR/html4/sgml/entities.html + 'clubsuit': '♣', // http://www.w3.org/TR/html5/named-character-references.html + 'hearts': '♥', // http://www.w3.org/TR/html4/sgml/entities.html + 'heartsuit': '♥', // http://www.w3.org/TR/html5/named-character-references.html + 'diams': '♦', + 'sung': '♪', + 'flat': '♭', + 'natural': '♮', + 'sharp': '♯', + 'checkmark': '✓', + 'cross': '✗', + 'maltese': '✠', + 'sext': '✶', + 'VerticalSeparator': '❘', + 'lbbrk': '❲', + 'rbbrk': '❳', + 'bsolhsub': '⟈', + 'suphsol': '⟉', + 'lobrk': '⟦', + 'robrk': '⟧', + 'langle': '⟨', + 'rangle': '⟩', + 'Lang': '⟪', + 'Rang': '⟫', + 'loang': '⟬', + 'roang': '⟭', + 'xlarr': '⟵', + 'xrarr': '⟶', + 'xharr': '⟷', + 'xlArr': '⟸', + 'xrArr': '⟹', + 'xhArr': '⟺', + 'xmap': '⟼', + 'dzigrarr': '⟿', + 'nvlArr': '⤂', + 'nvrArr': '⤃', + 'nvHarr': '⤄', + 'Map': '⤅', + 'lbarr': '⤌', + 'rbarr': '⤍', + 'lBarr': '⤎', + 'rBarr': '⤏', + 'drbkarow': '⤐', + 'DDotrahd': '⤑', + 'UpArrowBar': '⤒', + 'DownArrowBar': '⤓', + 'Rarrtl': '⤖', + 'latail': '⤙', + 'ratail': '⤚', + 'lAtail': '⤛', + 'rAtail': '⤜', + 'larrfs': '⤝', + 'rarrfs': '⤞', + 'larrbfs': '⤟', + 'rarrbfs': '⤠', + 'nwarhk': '⤣', + 'nearhk': '⤤', + 'searhk': '⤥', + 'swarhk': '⤦', + 'nwnear': '⤧', + 'toea': '⤨', + 'tosa': '⤩', + 'swnwar': '⤪', + 'rarrc': '⤳', + 'cudarrr': '⤵', + 'ldca': '⤶', + 'rdca': '⤷', + 'cudarrl': '⤸', + 'larrpl': '⤹', + 'curarrm': '⤼', + 'cularrp': '⤽', + 'rarrpl': '⥅', + 'harrcir': '⥈', + 'Uarrocir': '⥉', + 'lurdshar': '⥊', + 'ldrushar': '⥋', + 'LeftRightVector': '⥎', + 'RightUpDownVector': '⥏', + 'DownLeftRightVector': '⥐', + 'LeftUpDownVector': '⥑', + 'LeftVectorBar': '⥒', + 'RightVectorBar': '⥓', + 'RightUpVectorBar': '⥔', + 'RightDownVectorBar': '⥕', + 'DownLeftVectorBar': '⥖', + 'DownRightVectorBar': '⥗', + 'LeftUpVectorBar': '⥘', + 'LeftDownVectorBar': '⥙', + 'LeftTeeVector': '⥚', + 'RightTeeVector': '⥛', + 'RightUpTeeVector': '⥜', + 'RightDownTeeVector': '⥝', + 'DownLeftTeeVector': '⥞', + 'DownRightTeeVector': '⥟', + 'LeftUpTeeVector': '⥠', + 'LeftDownTeeVector': '⥡', + 'lHar': '⥢', + 'uHar': '⥣', + 'rHar': '⥤', + 'dHar': '⥥', + 'luruhar': '⥦', + 'ldrdhar': '⥧', + 'ruluhar': '⥨', + 'rdldhar': '⥩', + 'lharul': '⥪', + 'llhard': '⥫', + 'rharul': '⥬', + 'lrhard': '⥭', + 'udhar': '⥮', + 'duhar': '⥯', + 'RoundImplies': '⥰', + 'erarr': '⥱', + 'simrarr': '⥲', + 'larrsim': '⥳', + 'rarrsim': '⥴', + 'rarrap': '⥵', + 'ltlarr': '⥶', + 'gtrarr': '⥸', + 'subrarr': '⥹', + 'suplarr': '⥻', + 'lfisht': '⥼', + 'rfisht': '⥽', + 'ufisht': '⥾', + 'dfisht': '⥿', + 'lopar': '⦅', + 'ropar': '⦆', + 'lbrke': '⦋', + 'rbrke': '⦌', + 'lbrkslu': '⦍', + 'rbrksld': '⦎', + 'lbrksld': '⦏', + 'rbrkslu': '⦐', + 'langd': '⦑', + 'rangd': '⦒', + 'lparlt': '⦓', + 'rpargt': '⦔', + 'gtlPar': '⦕', + 'ltrPar': '⦖', + 'vzigzag': '⦚', + 'vangrt': '⦜', + 'angrtvbd': '⦝', + 'ange': '⦤', + 'range': '⦥', + 'dwangle': '⦦', + 'uwangle': '⦧', + 'angmsdaa': '⦨', + 'angmsdab': '⦩', + 'angmsdac': '⦪', + 'angmsdad': '⦫', + 'angmsdae': '⦬', + 'angmsdaf': '⦭', + 'angmsdag': '⦮', + 'angmsdah': '⦯', + 'bemptyv': '⦰', + 'demptyv': '⦱', + 'cemptyv': '⦲', + 'raemptyv': '⦳', + 'laemptyv': '⦴', + 'ohbar': '⦵', + 'omid': '⦶', + 'opar': '⦷', + 'operp': '⦹', + 'olcross': '⦻', + 'odsold': '⦼', + 'olcir': '⦾', + 'ofcir': '⦿', + 'olt': '⧀', + 'ogt': '⧁', + 'cirscir': '⧂', + 'cirE': '⧃', + 'solb': '⧄', + 'bsolb': '⧅', + 'boxbox': '⧉', + 'trisb': '⧍', + 'rtriltri': '⧎', + 'LeftTriangleBar': '⧏', + 'RightTriangleBar': '⧐', + 'iinfin': '⧜', + 'infintie': '⧝', + 'nvinfin': '⧞', + 'eparsl': '⧣', + 'smeparsl': '⧤', + 'eqvparsl': '⧥', + 'lozf': '⧫', + 'RuleDelayed': '⧴', + 'dsol': '⧶', + 'xodot': '⨀', + 'xoplus': '⨁', + 'xotime': '⨂', + 'xuplus': '⨄', + 'xsqcup': '⨆', + 'qint': '⨌', + 'fpartint': '⨍', + 'cirfnint': '⨐', + 'awint': '⨑', + 'rppolint': '⨒', + 'scpolint': '⨓', + 'npolint': '⨔', + 'pointint': '⨕', + 'quatint': '⨖', + 'intlarhk': '⨗', + 'pluscir': '⨢', + 'plusacir': '⨣', + 'simplus': '⨤', + 'plusdu': '⨥', + 'plussim': '⨦', + 'plustwo': '⨧', + 'mcomma': '⨩', + 'minusdu': '⨪', + 'loplus': '⨭', + 'roplus': '⨮', + 'Cross': '⨯', + 'timesd': '⨰', + 'timesbar': '⨱', + 'smashp': '⨳', + 'lotimes': '⨴', + 'rotimes': '⨵', + 'otimesas': '⨶', + 'Otimes': '⨷', + 'odiv': '⨸', + 'triplus': '⨹', + 'triminus': '⨺', + 'tritime': '⨻', + 'iprod': '⨼', + 'amalg': '⨿', + 'capdot': '⩀', + 'ncup': '⩂', + 'ncap': '⩃', + 'capand': '⩄', + 'cupor': '⩅', + 'cupcap': '⩆', + 'capcup': '⩇', + 'cupbrcap': '⩈', + 'capbrcup': '⩉', + 'cupcup': '⩊', + 'capcap': '⩋', + 'ccups': '⩌', + 'ccaps': '⩍', + 'ccupssm': '⩐', + 'And': '⩓', + 'Or': '⩔', + 'andand': '⩕', + 'oror': '⩖', + 'orslope': '⩗', + 'andslope': '⩘', + 'andv': '⩚', + 'orv': '⩛', + 'andd': '⩜', + 'ord': '⩝', + 'wedbar': '⩟', + 'sdote': '⩦', + 'simdot': '⩪', + 'congdot': '⩭', + 'easter': '⩮', + 'apacir': '⩯', + 'apE': '⩰', + 'eplus': '⩱', + 'pluse': '⩲', + 'Esim': '⩳', + 'Colone': '⩴', + 'Equal': '⩵', + 'eDDot': '⩷', + 'equivDD': '⩸', + 'ltcir': '⩹', + 'gtcir': '⩺', + 'ltquest': '⩻', + 'gtquest': '⩼', + 'les': '⩽', + 'ges': '⩾', + 'lesdot': '⩿', + 'gesdot': '⪀', + 'lesdoto': '⪁', + 'gesdoto': '⪂', + 'lesdotor': '⪃', + 'gesdotol': '⪄', + 'lessapprox': '⪅', + 'gtrapprox': '⪆', + 'lneq': '⪇', + 'gneq': '⪈', + 'lnapprox': '⪉', + 'gnapprox': '⪊', + 'lesseqqgtr': '⪋', + 'gtreqqless': '⪌', + 'lsime': '⪍', + 'gsime': '⪎', + 'lsimg': '⪏', + 'gsiml': '⪐', + 'lgE': '⪑', + 'glE': '⪒', + 'lesges': '⪓', + 'gesles': '⪔', + 'eqslantless': '⪕', + 'eqslantgtr': '⪖', + 'elsdot': '⪗', + 'egsdot': '⪘', + 'el': '⪙', + 'eg': '⪚', + 'siml': '⪝', + 'simg': '⪞', + 'simlE': '⪟', + 'simgE': '⪠', + 'LessLess': '⪡', + 'GreaterGreater': '⪢', + 'glj': '⪤', + 'gla': '⪥', + 'ltcc': '⪦', + 'gtcc': '⪧', + 'lescc': '⪨', + 'gescc': '⪩', + 'smt': '⪪', + 'lat': '⪫', + 'smte': '⪬', + 'late': '⪭', + 'bumpE': '⪮', + 'preceq': '⪯', + 'succeq': '⪰', + 'prE': '⪳', + 'scE': '⪴', + 'prnE': '⪵', + 'succneqq': '⪶', + 'precapprox': '⪷', + 'succapprox': '⪸', + 'prnap': '⪹', + 'succnapprox': '⪺', + 'Pr': '⪻', + 'Sc': '⪼', + 'subdot': '⪽', + 'supdot': '⪾', + 'subplus': '⪿', + 'supplus': '⫀', + 'submult': '⫁', + 'supmult': '⫂', + 'subedot': '⫃', + 'supedot': '⫄', + 'subseteqq': '⫅', + 'supseteqq': '⫆', + 'subsim': '⫇', + 'supsim': '⫈', + 'subsetneqq': '⫋', + 'supsetneqq': '⫌', + 'csub': '⫏', + 'csup': '⫐', + 'csube': '⫑', + 'csupe': '⫒', + 'subsup': '⫓', + 'supsub': '⫔', + 'subsub': '⫕', + 'supsup': '⫖', + 'suphsub': '⫗', + 'supdsub': '⫘', + 'forkv': '⫙', + 'topfork': '⫚', + 'mlcp': '⫛', + 'DoubleLeftTee': '⫤', + 'Vdashl': '⫦', + 'Barv': '⫧', + 'vBar': '⫨', + 'vBarv': '⫩', + 'Vbar': '⫫', + 'Not': '⫬', + 'bNot': '⫭', + 'rnmid': '⫮', + 'cirmid': '⫯', + 'midcir': '⫰', + 'topcir': '⫱', + 'nhpar': '⫲', + 'parsim': '⫳', + 'parsl': '⫽', + 'fflig': 'ff', + 'filig': 'fi', + 'fllig': 'fl', + 'ffilig': 'ffi', + 'ffllig': 'ffl', + 'Ascr': '풜', + 'Cscr': '풞', + 'Dscr': '풟', + 'Gscr': '풢', + 'Jscr': '풥', + 'Kscr': '풦', + 'Nscr': '풩', + 'Oscr': '풪', + 'Pscr': '풫', + 'Qscr': '풬', + 'Sscr': '풮', + 'Tscr': '풯', + 'Uscr': '풰', + 'Vscr': '풱', + 'Wscr': '풲', + 'Xscr': '풳', + 'Yscr': '풴', + 'Zscr': '풵', + 'ascr': '풶', + 'bscr': '풷', + 'cscr': '풸', + 'dscr': '풹', + 'fscr': '풻', + 'hscr': '풽', + 'iscr': '풾', + 'jscr': '풿', + 'kscr': '퓀', + 'lscr': '퓁', + 'mscr': '퓂', + 'nscr': '퓃', + 'pscr': '퓅', + 'qscr': '퓆', + 'rscr': '퓇', + 'sscr': '퓈', + 'tscr': '퓉', + 'uscr': '퓊', + 'vscr': '퓋', + 'wscr': '퓌', + 'xscr': '퓍', + 'yscr': '퓎', + 'zscr': '퓏', + 'Afr': '프', + 'Bfr': '픅', + 'Dfr': '픇', + 'Efr': '픈', + 'Ffr': '픉', + 'Gfr': '픊', + 'Jfr': '픍', + 'Kfr': '픎', + 'Lfr': '픏', + 'Mfr': '픐', + 'Nfr': '픑', + 'Ofr': '픒', + 'Pfr': '픓', + 'Qfr': '픔', + 'Sfr': '픖', + 'Tfr': '픗', + 'Ufr': '픘', + 'Vfr': '픙', + 'Wfr': '픚', + 'Xfr': '픛', + 'Yfr': '픜', + 'afr': '픞', + 'bfr': '픟', + 'cfr': '픠', + 'dfr': '픡', + 'efr': '픢', + 'ffr': '픣', + 'gfr': '픤', + 'hfr': '픥', + 'ifr': '픦', + 'jfr': '픧', + 'kfr': '픨', + 'lfr': '픩', + 'mfr': '픪', + 'nfr': '픫', + 'ofr': '픬', + 'pfr': '픭', + 'qfr': '픮', + 'rfr': '픯', + 'sfr': '픰', + 'tfr': '픱', + 'ufr': '픲', + 'vfr': '픳', + 'wfr': '픴', + 'xfr': '픵', + 'yfr': '픶', + 'zfr': '픷', + 'Aopf': '픸', + 'Bopf': '픹', + 'Dopf': '픻', + 'Eopf': '피', + 'Fopf': '픽', + 'Gopf': '픾', + 'Iopf': '핀', + 'Jopf': '핁', + 'Kopf': '핂', + 'Lopf': '핃', + 'Mopf': '필', + 'Oopf': '핆', + 'Sopf': '핊', + 'Topf': '핋', + 'Uopf': '핌', + 'Vopf': '핍', + 'Wopf': '핎', + 'Xopf': '핏', + 'Yopf': '핐', + 'aopf': '핒', + 'bopf': '핓', + 'copf': '핔', + 'dopf': '핕', + 'eopf': '핖', + 'fopf': '핗', + 'gopf': '하', + 'hopf': '학', + 'iopf': '핚', + 'jopf': '핛', + 'kopf': '한', + 'lopf': '핝', + 'mopf': '핞', + 'nopf': '핟', + 'oopf': '할', + 'popf': '핡', + 'qopf': '핢', + 'ropf': '핣', + 'sopf': '핤', + 'topf': '핥', + 'uopf': '핦', + 'vopf': '핧', + 'wopf': '함', + 'xopf': '합', + 'yopf': '핪', + 'zopf': '핫' +}; + +var specialCharEntities = { + '&': '&', + '"': '"', + '<': '<', + '>': '>', + '\xA0': ' ' +}; + +var entityRegExp = /&(?:#([0-9]+)|#x([0-9a-f]+)|([a-z0-9]+));/gi; +var attributeModeSpecialCharRegExp = /["&<>\xA0]/g; +var nonAttributeModeSpecialCharRegExp = /[&<>\xA0]/g; + +exports.HTMLDecode = function decode(s) { + if (!s) return ''; + return s.replace(entityRegExp, function ($0, decimalStr, hexStr, entityName) { + if (decimalStr) { + return String.fromCharCode(parseInt(decimalStr, 10)); + } else if (hexStr) { + return String.fromCharCode(parseInt(hexStr, 16)); + } else { + // Fall back to the original string if we don't know the entity, as per browser behavior: + return charByEntityName[entityName] || $0; + } + }); +}; + +function specialCharToEntity(s) { + var entity = specialCharEntities[s]; + return entity ? entity : s; +} + +exports.HTMLEncode = function encode(s, attributeMode) { + if (!s) return ''; + if (!s.replace) return s; + if(attributeMode) { + return s.replace(attributeModeSpecialCharRegExp, specialCharToEntity); + } else { + return s.replace(nonAttributeModeSpecialCharRegExp, specialCharToEntity); + } +}; diff --git a/node_modules/jsdom/lib/jsdom/browser/htmltodom.js b/node_modules/jsdom/lib/jsdom/browser/htmltodom.js new file mode 100644 index 0000000..1ea28cc --- /dev/null +++ b/node_modules/jsdom/lib/jsdom/browser/htmltodom.js @@ -0,0 +1,187 @@ +var HTMLDecode = require('./htmlencoding').HTMLDecode; + +function HtmlToDom(parser) { + + if(parser && parser.write) { + // sax parser + this.appendHtmlToElement = function(html, element){ + + var currentElement = element, currentLevel = 0; + + parser.onerror = function (e) {}; + + parser.ontext = function (t) { + var ownerDocument = currentElement.ownerDocument || currentElement; + var newText = ownerDocument.createTextNode(t); + currentElement.appendChild(newText); + }; + + parser.onopentag = function (node) { + var nodeName = node.name.toLowerCase(), + document = currentElement.ownerDocument || currentElement, + newElement = document.createElement(nodeName), + i = 0, + length = (node.attributes && node.attributes.length) ? + node.attributes.length : + 0; + + for (i in node.attributes) { + if (node.attributes.hasOwnProperty(i)) { + newElement.setAttribute(i, node.attributes[i]); + } + } + + for (i=0; i 0) { + if (element.nodeType == 9) { + new parser.Parser({document: element}).parse(html); + } + else { + var p = new parser.Parser({document: element.ownerDocument}); + p.parse_fragment(html, element); + } + } + }; + } else { + + this.appendHtmlToElement = function(){ + console.log(''); + console.log('###########################################################'); + console.log('# WARNING: No HTML parser could be found.'); + console.log('# Element.innerHTML setter support has been disabled'); + console.log('# Element.innerHTML getter support will still function'); + console.log('# Download: http://github.com/tautologistics/node-htmlparser'); + console.log('###########################################################'); + console.log(''); + }; + + } +}; + +// utility function for forgiving parser +function setChild(parent, node) { + + var c, newNode, currentDocument = parent._ownerDocument || parent; + + switch (node.type) + { + case 'tag': + case 'script': + case 'style': + try { + newNode = currentDocument.createElement(node.name); + if (node.location) { + newNode.sourceLocation = node.location; + newNode.sourceLocation.file = parent.sourceLocation.file; + } + } catch (err) { + currentDocument.raise('error', 'invalid markup', { + exception: err, + node : node + }); + + return null; + } + break; + + case 'text': + // Decode HTML entities if we're not inside a + , Style: "style" //Special tag + , Tag: "tag" //Any tag that isn't special +} + +function Parser (handler, options) { + this._options = options ? options : { }; + if (this._options.includeLocation == undefined) { + this._options.includeLocation = false; //Do not track element position in document by default + } + + this.validateHandler(handler); + this._handler = handler; + this.reset(); +} + + //**"Static"**// + //Regular expressions used for cleaning up and parsing (stateless) + Parser._reTrim = /(^\s+|\s+$)/g; //Trim leading/trailing whitespace + Parser._reTrimComment = /(^\!--|--$)/g; //Remove comment tag markup from comment contents + Parser._reWhitespace = /\s/g; //Used to find any whitespace to split on + Parser._reTagName = /^\s*(\/?)\s*([^\s\/]+)/; //Used to find the tag name for an element + + //Regular expressions used for parsing (stateful) + Parser._reAttrib = //Find attributes in a tag + /([^=<>\"\'\s]+)\s*=\s*"([^"]*)"|([^=<>\"\'\s]+)\s*=\s*'([^']*)'|([^=<>\"\'\s]+)\s*=\s*([^'"\s]+)|([^=<>\"\'\s\/]+)/g; + Parser._reTags = /[\<\>]/g; //Find tag markers + + //**Public**// + //Methods// + //Parses a complete HTML and pushes it to the handler + Parser.prototype.parseComplete = function Parser$parseComplete (data) { + this.reset(); + this.parseChunk(data); + this.done(); + } + + //Parses a piece of an HTML document + Parser.prototype.parseChunk = function Parser$parseChunk (data) { + if (this._done) + this.handleError(new Error("Attempted to parse chunk after parsing already done")); + this._buffer += data; //FIXME: this can be a bottleneck + this.parseTags(); + } + + //Tells the parser that the HTML being parsed is complete + Parser.prototype.done = function Parser$done () { + if (this._done) + return; + this._done = true; + + //Push any unparsed text into a final element in the element list + if (this._buffer.length) { + var rawData = this._buffer; + this._buffer = ""; + var element = { + raw: rawData + , data: (this._parseState == ElementType.Text) ? rawData : rawData.replace(Parser._reTrim, "") + , type: this._parseState + }; + if (this._parseState == ElementType.Tag || this._parseState == ElementType.Script || this._parseState == ElementType.Style) + element.name = this.parseTagName(element.data); + this.parseAttribs(element); + this._elements.push(element); + } + + this.writeHandler(); + this._handler.done(); + } + + //Resets the parser to a blank state, ready to parse a new HTML document + Parser.prototype.reset = function Parser$reset () { + this._buffer = ""; + this._done = false; + this._elements = []; + this._elementsCurrent = 0; + this._current = 0; + this._next = 0; + this._location = { + row: 0 + , col: 0 + , charOffset: 0 + , inBuffer: 0 + }; + this._parseState = ElementType.Text; + this._prevTagSep = ''; + this._tagStack = []; + this._handler.reset(); + } + + //**Private**// + //Properties// + Parser.prototype._options = null; //Parser options for how to behave + Parser.prototype._handler = null; //Handler for parsed elements + Parser.prototype._buffer = null; //Buffer of unparsed data + Parser.prototype._done = false; //Flag indicating whether parsing is done + Parser.prototype._elements = null; //Array of parsed elements + Parser.prototype._elementsCurrent = 0; //Pointer to last element in _elements that has been processed + Parser.prototype._current = 0; //Position in data that has already been parsed + Parser.prototype._next = 0; //Position in data of the next tag marker (<>) + Parser.prototype._location = null; //Position tracking for elements in a stream + Parser.prototype._parseState = ElementType.Text; //Current type of element being parsed + Parser.prototype._prevTagSep = ''; //Previous tag marker found + //Stack of element types previously encountered; keeps track of when + //parsing occurs inside a script/comment/style tag + Parser.prototype._tagStack = null; + + //Methods// + //Takes an array of elements and parses any found attributes + Parser.prototype.parseTagAttribs = function Parser$parseTagAttribs (elements) { + var idxEnd = elements.length; + var idx = 0; + + while (idx < idxEnd) { + var element = elements[idx++]; + if (element.type == ElementType.Tag || element.type == ElementType.Script || element.type == ElementType.style) + this.parseAttribs(element); + } + + return(elements); + } + + //Takes an element and adds an "attribs" property for any element attributes found + Parser.prototype.parseAttribs = function Parser$parseAttribs (element) { + //Only parse attributes for tags + if (element.type != ElementType.Script && element.type != ElementType.Style && element.type != ElementType.Tag) + return; + + var tagName = element.data.split(Parser._reWhitespace, 1)[0]; + var attribRaw = element.data.substring(tagName.length); + if (attribRaw.length < 1) + return; + + var match; + Parser._reAttrib.lastIndex = 0; + while (match = Parser._reAttrib.exec(attribRaw)) { + if (element.attribs == undefined) + element.attribs = {}; + + if (typeof match[1] == "string" && match[1].length) { + element.attribs[match[1]] = match[2]; + } else if (typeof match[3] == "string" && match[3].length) { + element.attribs[match[3].toString()] = match[4].toString(); + } else if (typeof match[5] == "string" && match[5].length) { + element.attribs[match[5]] = match[6]; + } else if (typeof match[7] == "string" && match[7].length) { + element.attribs[match[7]] = match[7]; + } + } + } + + //Extracts the base tag name from the data value of an element + Parser.prototype.parseTagName = function Parser$parseTagName (data) { + if (data == null || data == "") + return(""); + var match = Parser._reTagName.exec(data); + if (!match) + return(""); + return((match[1] ? "/" : "") + match[2]); + } + + //Parses through HTML text and returns an array of found elements + //I admit, this function is rather large but splitting up had an noticeable impact on speed + Parser.prototype.parseTags = function Parser$parseTags () { + var bufferEnd = this._buffer.length - 1; + while (Parser._reTags.test(this._buffer)) { + this._next = Parser._reTags.lastIndex - 1; + var tagSep = this._buffer.charAt(this._next); //The currently found tag marker + var rawData = this._buffer.substring(this._current, this._next); //The next chunk of data to parse + + //A new element to eventually be appended to the element list + var element = { + raw: rawData + , data: (this._parseState == ElementType.Text) ? rawData : rawData.replace(Parser._reTrim, "") + , type: this._parseState + }; + + var elementName = this.parseTagName(element.data); + + //This section inspects the current tag stack and modifies the current + //element if we're actually parsing a special area (script/comment/style tag) + if (this._tagStack.length) { //We're parsing inside a script/comment/style tag + if (this._tagStack[this._tagStack.length - 1] == ElementType.Script) { //We're currently in a script tag + if (elementName.toLowerCase() == "/script") //Actually, we're no longer in a script tag, so pop it off the stack + this._tagStack.pop(); + else { //Not a closing script tag + if (element.raw.indexOf("!--") != 0) { //Make sure we're not in a comment + //All data from here to script close is now a text element + element.type = ElementType.Text; + //If the previous element is text, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Text) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep + element.raw; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + } + } + } + } + else if (this._tagStack[this._tagStack.length - 1] == ElementType.Style) { //We're currently in a style tag + if (elementName.toLowerCase() == "/style") //Actually, we're no longer in a style tag, so pop it off the stack + this._tagStack.pop(); + else { + if (element.raw.indexOf("!--") != 0) { //Make sure we're not in a comment + //All data from here to style close is now a text element + element.type = ElementType.Text; + //If the previous element is text, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Text) { + var prevElement = this._elements[this._elements.length - 1]; + if (element.raw != "") { + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep + element.raw; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + } else { //Element is empty, so just append the last tag marker found + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep; + } + } else { //The previous element was not text + if (element.raw != "") { + element.raw = element.data = element.raw; + } + } + } + } + } + else if (this._tagStack[this._tagStack.length - 1] == ElementType.Comment) { //We're currently in a comment tag + var rawLen = element.raw.length; + if (element.raw.charAt(rawLen - 2) == "-" && element.raw.charAt(rawLen - 1) == "-" && tagSep == ">") { + //Actually, we're no longer in a style tag, so pop it off the stack + this._tagStack.pop(); + //If the previous element is a comment, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Comment) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = (prevElement.raw + element.raw).replace(Parser._reTrimComment, ""); + element.raw = element.data = ""; //This causes the current element to not be added to the element list + element.type = ElementType.Text; + } + else //Previous element not a comment + element.type = ElementType.Comment; //Change the current element's type to a comment + } + else { //Still in a comment tag + element.type = ElementType.Comment; + //If the previous element is a comment, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Comment) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + element.raw + tagSep; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + element.type = ElementType.Text; + } + else + element.raw = element.data = element.raw + tagSep; + } + } + } + + //Processing of non-special tags + if (element.type == ElementType.Tag) { + element.name = elementName; + var elementNameCI = elementName.toLowerCase(); + + if (element.raw.indexOf("!--") == 0) { //This tag is really comment + element.type = ElementType.Comment; + delete element["name"]; + var rawLen = element.raw.length; + //Check if the comment is terminated in the current element + if (element.raw.charAt(rawLen - 1) == "-" && element.raw.charAt(rawLen - 2) == "-" && tagSep == ">") + element.raw = element.data = element.raw.replace(Parser._reTrimComment, ""); + else { //It's not so push the comment onto the tag stack + element.raw += tagSep; + this._tagStack.push(ElementType.Comment); + } + } + else if (element.raw.indexOf("!") == 0 || element.raw.indexOf("?") == 0) { + element.type = ElementType.Directive; + //TODO: what about CDATA? + } + else if (elementNameCI == "script") { + element.type = ElementType.Script; + //Special tag, push onto the tag stack if not terminated + if (element.data.charAt(element.data.length - 1) != "/") + this._tagStack.push(ElementType.Script); + } + else if (elementNameCI == "/script") + element.type = ElementType.Script; + else if (elementNameCI == "style") { + element.type = ElementType.Style; + //Special tag, push onto the tag stack if not terminated + if (element.data.charAt(element.data.length - 1) != "/") + this._tagStack.push(ElementType.Style); + } + else if (elementNameCI == "/style") + element.type = ElementType.Style; + if (element.name && element.name.charAt(0) == "/") + element.data = element.name; + } + + //Add all tags and non-empty text elements to the element list + if (element.raw != "" || element.type != ElementType.Text) { + if (this._options.includeLocation && !element.location) { + element.location = this.getLocation(element.type == ElementType.Tag); + } + this.parseAttribs(element); + this._elements.push(element); + //If tag self-terminates, add an explicit, separate closing tag + if ( + element.type != ElementType.Text + && + element.type != ElementType.Comment + && + element.type != ElementType.Directive + && + element.data.charAt(element.data.length - 1) == "/" + ) + this._elements.push({ + raw: "/" + element.name + , data: "/" + element.name + , name: "/" + element.name + , type: element.type + }); + } + this._parseState = (tagSep == "<") ? ElementType.Tag : ElementType.Text; + this._current = this._next + 1; + this._prevTagSep = tagSep; + } + + if (this._options.includeLocation) { + this.getLocation(); + this._location.row += this._location.inBuffer; + this._location.inBuffer = 0; + this._location.charOffset = 0; + } + this._buffer = (this._current <= bufferEnd) ? this._buffer.substring(this._current) : ""; + this._current = 0; + + this.writeHandler(); + } + + Parser.prototype.getLocation = function Parser$getLocation (startTag) { + var c, + l = this._location, + end = this._current - (startTag ? 1 : 0), + chunk = startTag && l.charOffset == 0 && this._current == 0; + + for (; l.charOffset < end; l.charOffset++) { + c = this._buffer.charAt(l.charOffset); + if (c == '\n') { + l.inBuffer++; + l.col = 0; + } else if (c != '\r') { + l.col++; + } + } + return { + line: l.row + l.inBuffer + 1 + , col: l.col + (chunk ? 0: 1) + }; + } + + //Checks the handler to make it is an object with the right "interface" + Parser.prototype.validateHandler = function Parser$validateHandler (handler) { + if ((typeof handler) != "object") + throw new Error("Handler is not an object"); + if ((typeof handler.reset) != "function") + throw new Error("Handler method 'reset' is invalid"); + if ((typeof handler.done) != "function") + throw new Error("Handler method 'done' is invalid"); + if ((typeof handler.writeTag) != "function") + throw new Error("Handler method 'writeTag' is invalid"); + if ((typeof handler.writeText) != "function") + throw new Error("Handler method 'writeText' is invalid"); + if ((typeof handler.writeComment) != "function") + throw new Error("Handler method 'writeComment' is invalid"); + if ((typeof handler.writeDirective) != "function") + throw new Error("Handler method 'writeDirective' is invalid"); + } + + //Writes parsed elements out to the handler + Parser.prototype.writeHandler = function Parser$writeHandler (forceFlush) { + forceFlush = !!forceFlush; + if (this._tagStack.length && !forceFlush) + return; + while (this._elements.length) { + var element = this._elements.shift(); + switch (element.type) { + case ElementType.Comment: + this._handler.writeComment(element); + break; + case ElementType.Directive: + this._handler.writeDirective(element); + break; + case ElementType.Text: + this._handler.writeText(element); + break; + default: + this._handler.writeTag(element); + break; + } + } + } + + Parser.prototype.handleError = function Parser$handleError (error) { + if ((typeof this._handler.error) == "function") + this._handler.error(error); + else + throw error; + } + +//TODO: make this a trully streamable handler +function RssHandler (callback) { + RssHandler.super_.call(this, callback, { ignoreWhitespace: true, verbose: false, enforceEmptyTags: false }); +} +inherits(RssHandler, DefaultHandler); + + RssHandler.prototype.done = function RssHandler$done () { + var feed = { }; + var feedRoot; + + var found = DomUtils.getElementsByTagName(function (value) { return(value == "rss" || value == "feed"); }, this.dom, false); + if (found.length) { + feedRoot = found[0]; + } + if (feedRoot) { + if (feedRoot.name == "rss") { + feed.type = "rss"; + feedRoot = feedRoot.children[0]; // + feed.id = ""; + try { + feed.title = DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.link = DomUtils.getElementsByTagName("link", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.description = DomUtils.getElementsByTagName("description", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.updated = new Date(DomUtils.getElementsByTagName("lastBuildDate", feedRoot.children, false)[0].children[0].data); + } catch (ex) { } + try { + feed.author = DomUtils.getElementsByTagName("managingEditor", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + feed.items = []; + DomUtils.getElementsByTagName("item", feedRoot.children).forEach(function (item, index, list) { + var entry = {}; + try { + entry.id = DomUtils.getElementsByTagName("guid", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.title = DomUtils.getElementsByTagName("title", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.link = DomUtils.getElementsByTagName("link", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.description = DomUtils.getElementsByTagName("description", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.pubDate = new Date(DomUtils.getElementsByTagName("pubDate", item.children, false)[0].children[0].data); + } catch (ex) { } + feed.items.push(entry); + }); + } else { + feed.type = "atom"; + try { + feed.id = DomUtils.getElementsByTagName("id", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.title = DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.link = DomUtils.getElementsByTagName("link", feedRoot.children, false)[0].attribs.href; + } catch (ex) { } + try { + feed.description = DomUtils.getElementsByTagName("subtitle", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.updated = new Date(DomUtils.getElementsByTagName("updated", feedRoot.children, false)[0].children[0].data); + } catch (ex) { } + try { + feed.author = DomUtils.getElementsByTagName("email", feedRoot.children, true)[0].children[0].data; + } catch (ex) { } + feed.items = []; + DomUtils.getElementsByTagName("entry", feedRoot.children).forEach(function (item, index, list) { + var entry = {}; + try { + entry.id = DomUtils.getElementsByTagName("id", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.title = DomUtils.getElementsByTagName("title", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.link = DomUtils.getElementsByTagName("link", item.children, false)[0].attribs.href; + } catch (ex) { } + try { + entry.description = DomUtils.getElementsByTagName("summary", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.pubDate = new Date(DomUtils.getElementsByTagName("updated", item.children, false)[0].children[0].data); + } catch (ex) { } + feed.items.push(entry); + }); + } + + this.dom = feed; + } + RssHandler.super_.prototype.done.call(this); + } + +/////////////////////////////////////////////////// + +function DefaultHandler (callback, options) { + this.reset(); + this._options = options ? options : { }; + if (this._options.ignoreWhitespace == undefined) + this._options.ignoreWhitespace = false; //Keep whitespace-only text nodes + if (this._options.verbose == undefined) + this._options.verbose = true; //Keep data property for tags and raw property for all + if (this._options.enforceEmptyTags == undefined) + this._options.enforceEmptyTags = true; //Don't allow children for HTML tags defined as empty in spec + if ((typeof callback) == "function") + this._callback = callback; +} + + //**"Static"**// + //HTML Tags that shouldn't contain child nodes + DefaultHandler._emptyTags = { + area: 1 + , base: 1 + , basefont: 1 + , br: 1 + , col: 1 + , frame: 1 + , hr: 1 + , img: 1 + , input: 1 + , isindex: 1 + , link: 1 + , meta: 1 + , param: 1 + , embed: 1 + } + //Regex to detect whitespace only text nodes + DefaultHandler.reWhitespace = /^\s*$/; + + //**Public**// + //Properties// + DefaultHandler.prototype.dom = null; //The hierarchical object containing the parsed HTML + //Methods// + //Resets the handler back to starting state + DefaultHandler.prototype.reset = function DefaultHandler$reset() { + this.dom = []; + this._done = false; + this._tagStack = []; + this._tagStack.last = function DefaultHandler$_tagStack$last () { + return(this.length ? this[this.length - 1] : null); + } + } + //Signals the handler that parsing is done + DefaultHandler.prototype.done = function DefaultHandler$done () { + this._done = true; + this.handleCallback(null); + } + DefaultHandler.prototype.writeTag = function DefaultHandler$writeTag (element) { + this.handleElement(element); + } + DefaultHandler.prototype.writeText = function DefaultHandler$writeText (element) { + if (this._options.ignoreWhitespace) + if (DefaultHandler.reWhitespace.test(element.data)) + return; + this.handleElement(element); + } + DefaultHandler.prototype.writeComment = function DefaultHandler$writeComment (element) { + this.handleElement(element); + } + DefaultHandler.prototype.writeDirective = function DefaultHandler$writeDirective (element) { + this.handleElement(element); + } + DefaultHandler.prototype.error = function DefaultHandler$error (error) { + this.handleCallback(error); + } + + //**Private**// + //Properties// + DefaultHandler.prototype._options = null; //Handler options for how to behave + DefaultHandler.prototype._callback = null; //Callback to respond to when parsing done + DefaultHandler.prototype._done = false; //Flag indicating whether handler has been notified of parsing completed + DefaultHandler.prototype._tagStack = null; //List of parents to the currently element being processed + //Methods// + DefaultHandler.prototype.handleCallback = function DefaultHandler$handleCallback (error) { + if ((typeof this._callback) != "function") + if (error) + throw error; + else + return; + this._callback(error, this.dom); + } + + DefaultHandler.prototype.isEmptyTag = function(element) { + var name = element.name.toLowerCase(); + if (name.charAt(0) == '/') { + name = name.substring(1); + } + return this._options.enforceEmptyTags && !!DefaultHandler._emptyTags[name]; + }; + + DefaultHandler.prototype.handleElement = function DefaultHandler$handleElement (element) { + if (this._done) + this.handleCallback(new Error("Writing to the handler after done() called is not allowed without a reset()")); + if (!this._options.verbose) { +// element.raw = null; //FIXME: Not clean + //FIXME: Serious performance problem using delete + delete element.raw; + if (element.type == "tag" || element.type == "script" || element.type == "style") + delete element.data; + } + if (!this._tagStack.last()) { //There are no parent elements + //If the element can be a container, add it to the tag stack and the top level list + if (element.type != ElementType.Text && element.type != ElementType.Comment && element.type != ElementType.Directive) { + if (element.name.charAt(0) != "/") { //Ignore closing tags that obviously don't have an opening tag + this.dom.push(element); + if (!this.isEmptyTag(element)) { //Don't add tags to the tag stack that can't have children + this._tagStack.push(element); + } + } + } + else //Otherwise just add to the top level list + this.dom.push(element); + } + else { //There are parent elements + //If the element can be a container, add it as a child of the element + //on top of the tag stack and then add it to the tag stack + if (element.type != ElementType.Text && element.type != ElementType.Comment && element.type != ElementType.Directive) { + if (element.name.charAt(0) == "/") { + //This is a closing tag, scan the tagStack to find the matching opening tag + //and pop the stack up to the opening tag's parent + var baseName = element.name.substring(1); + if (!this.isEmptyTag(element)) { + var pos = this._tagStack.length - 1; + while (pos > -1 && this._tagStack[pos--].name != baseName) { } + if (pos > -1 || this._tagStack[0].name == baseName) + while (pos < this._tagStack.length - 1) + this._tagStack.pop(); + } + } + else { //This is not a closing tag + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(element); + if (!this.isEmptyTag(element)) //Don't add tags to the tag stack that can't have children + this._tagStack.push(element); + } + } + else { //This is not a container element + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(element); + } + } + } + + var DomUtils = { + testElement: function DomUtils$testElement (options, element) { + if (!element) { + return false; + } + + for (var key in options) { + if (key == "tag_name") { + if (element.type != "tag" && element.type != "script" && element.type != "style") { + return false; + } + if (!options["tag_name"](element.name)) { + return false; + } + } else if (key == "tag_type") { + if (!options["tag_type"](element.type)) { + return false; + } + } else if (key == "tag_contains") { + if (element.type != "text" && element.type != "comment" && element.type != "directive") { + return false; + } + if (!options["tag_contains"](element.data)) { + return false; + } + } else { + if (!element.attribs || !options[key](element.attribs[key])) { + return false; + } + } + } + + return true; + } + + , getElements: function DomUtils$getElements (options, currentElement, recurse, limit) { + recurse = (recurse === undefined || recurse === null) || !!recurse; + limit = isNaN(parseInt(limit)) ? -1 : parseInt(limit); + + if (!currentElement) { + return([]); + } + + var found = []; + var elementList; + + function getTest (checkVal) { + return(function (value) { return(value == checkVal); }); + } + for (var key in options) { + if ((typeof options[key]) != "function") { + options[key] = getTest(options[key]); + } + } + + if (DomUtils.testElement(options, currentElement)) { + found.push(currentElement); + } + + if (limit >= 0 && found.length >= limit) { + return(found); + } + + if (recurse && currentElement.children) { + elementList = currentElement.children; + } else if (currentElement instanceof Array) { + elementList = currentElement; + } else { + return(found); + } + + for (var i = 0; i < elementList.length; i++) { + found = found.concat(DomUtils.getElements(options, elementList[i], recurse, limit)); + if (limit >= 0 && found.length >= limit) { + break; + } + } + + return(found); + } + + , getElementById: function DomUtils$getElementById (id, currentElement, recurse) { + var result = DomUtils.getElements({ id: id }, currentElement, recurse, 1); + return(result.length ? result[0] : null); + } + + , getElementsByTagName: function DomUtils$getElementsByTagName (name, currentElement, recurse, limit) { + return(DomUtils.getElements({ tag_name: name }, currentElement, recurse, limit)); + } + + , getElementsByTagType: function DomUtils$getElementsByTagType (type, currentElement, recurse, limit) { + return(DomUtils.getElements({ tag_type: type }, currentElement, recurse, limit)); + } + } + + function inherits (ctor, superCtor) { + var tempCtor = function(){}; + tempCtor.prototype = superCtor.prototype; + ctor.super_ = superCtor; + ctor.prototype = new tempCtor(); + ctor.prototype.constructor = ctor; + } + +exports.Parser = Parser; + +exports.DefaultHandler = DefaultHandler; + +exports.RssHandler = RssHandler; + +exports.ElementType = ElementType; + +exports.DomUtils = DomUtils; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/lib/htmlparser.min.js b/node_modules/jsdom/node_modules/htmlparser/lib/htmlparser.min.js new file mode 100644 index 0000000..c1281c5 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/lib/htmlparser.min.js @@ -0,0 +1,22 @@ +/*********************************************** +Copyright 2010, 2011, Chris Winberry . All rights reserved. +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. +***********************************************/ +/* v1.7.6 */ +(function(){function e(a,c){this._options=c?c:{};void 0==this._options.includeLocation&&(this._options.includeLocation=!1);this.validateHandler(a);this._handler=a;this.reset()}function j(a){j.super_.call(this,a,{ignoreWhitespace:!0,verbose:!1,enforceEmptyTags:!1})}function g(a,c){this.reset();this._options=c?c:{};void 0==this._options.ignoreWhitespace&&(this._options.ignoreWhitespace=!1);void 0==this._options.verbose&&(this._options.verbose=!0);void 0==this._options.enforceEmptyTags&&(this._options.enforceEmptyTags= !0);"function"==typeof a&&(this._callback=a)}if(!("function"==typeof require&&"object"==typeof exports&&"object"==typeof module&&"string"==typeof __filename&&"string"==typeof __dirname)){if(this.Tautologistics){if(this.Tautologistics.NodeHtmlParser)return}else this.Tautologistics={};this.Tautologistics.NodeHtmlParser={};exports=this.Tautologistics.NodeHtmlParser}var d={Text:"text",Directive:"directive",Comment:"comment",Script:"script",Style:"style",Tag:"tag"};e._reTrim=/(^\s+|\s+$)/g;e._reTrimComment= /(^\!--|--$)/g;e._reWhitespace=/\s/g;e._reTagName=/^\s*(\/?)\s*([^\s\/]+)/;e._reAttrib=/([^=<>\"\'\s]+)\s*=\s*"([^"]*)"|([^=<>\"\'\s]+)\s*=\s*'([^']*)'|([^=<>\"\'\s]+)\s*=\s*([^'"\s]+)|([^=<>\"\'\s\/]+)/g;e._reTags=/[\<\>]/g;e.prototype.parseComplete=function(a){this.reset();this.parseChunk(a);this.done()};e.prototype.parseChunk=function(a){this._done&&this.handleError(Error("Attempted to parse chunk after parsing already done"));this._buffer+=a;this.parseTags()};e.prototype.done=function(){if(!this._done){this._done= !0;if(this._buffer.length){var a=this._buffer;this._buffer="";a={raw:a,data:this._parseState==d.Text?a:a.replace(e._reTrim,""),type:this._parseState};if(this._parseState==d.Tag||this._parseState==d.Script||this._parseState==d.Style)a.name=this.parseTagName(a.data);this.parseAttribs(a);this._elements.push(a)}this.writeHandler();this._handler.done()}};e.prototype.reset=function(){this._buffer="";this._done=!1;this._elements=[];this._next=this._current=this._elementsCurrent=0;this._location={row:0,col:0, charOffset:0,inBuffer:0};this._parseState=d.Text;this._prevTagSep="";this._tagStack=[];this._handler.reset()};e.prototype._options=null;e.prototype._handler=null;e.prototype._buffer=null;e.prototype._done=!1;e.prototype._elements=null;e.prototype._elementsCurrent=0;e.prototype._current=0;e.prototype._next=0;e.prototype._location=null;e.prototype._parseState=d.Text;e.prototype._prevTagSep="";e.prototype._tagStack=null;e.prototype.parseTagAttribs=function(a){for(var c=a.length,b=0;bc.length)){var b;for(e._reAttrib.lastIndex=0;b=e._reAttrib.exec(c);)void 0==a.attribs&&(a.attribs={}),"string"==typeof b[1]&&b[1].length?a.attribs[b[1]]=b[2]:"string"==typeof b[3]&&b[3].length?a.attribs[b[3].toString()]=b[4].toString():"string"==typeof b[5]&& b[5].length?a.attribs[b[5]]=b[6]:"string"==typeof b[7]&&b[7].length&&(a.attribs[b[7]]=b[7])}}};e.prototype.parseTagName=function(a){if(null==a||""==a)return"";a=e._reTagName.exec(a);return!a?"":(a[1]?"/":"")+a[2]};e.prototype.parseTags=function(){for(var a=this._buffer.length-1;e._reTags.test(this._buffer);){this._next=e._reTags.lastIndex-1;var c=this._buffer.charAt(this._next),b=this._buffer.substring(this._current,this._next),b={raw:b,data:this._parseState==d.Text?b:b.replace(e._reTrim,""),type:this._parseState}, f=this.parseTagName(b.data);if(this._tagStack.length)if(this._tagStack[this._tagStack.length-1]==d.Script)if("/script"==f.toLowerCase())this._tagStack.pop();else{if(0!=b.raw.indexOf("!--")&&(b.type=d.Text,this._elements.length&&this._elements[this._elements.length-1].type==d.Text)){var h=this._elements[this._elements.length-1];h.raw=h.data=h.raw+this._prevTagSep+b.raw;b.raw=b.data=""}}else this._tagStack[this._tagStack.length-1]==d.Style?"/style"==f.toLowerCase()?this._tagStack.pop():0!=b.raw.indexOf("!--")&& (b.type=d.Text,this._elements.length&&this._elements[this._elements.length-1].type==d.Text?(h=this._elements[this._elements.length-1],""!=b.raw?(h.raw=h.data=h.raw+this._prevTagSep+b.raw,b.raw=b.data=""):h.raw=h.data=h.raw+this._prevTagSep):""!=b.raw&&(b.raw=b.data=b.raw)):this._tagStack[this._tagStack.length-1]==d.Comment&&(h=b.raw.length,"-"==b.raw.charAt(h-2)&&"-"==b.raw.charAt(h-1)&&">"==c?(this._tagStack.pop(),this._elements.length&&this._elements[this._elements.length-1].type==d.Comment?(h= this._elements[this._elements.length-1],h.raw=h.data=(h.raw+b.raw).replace(e._reTrimComment,""),b.raw=b.data="",b.type=d.Text):b.type=d.Comment):(b.type=d.Comment,this._elements.length&&this._elements[this._elements.length-1].type==d.Comment?(h=this._elements[this._elements.length-1],h.raw=h.data=h.raw+b.raw+c,b.raw=b.data="",b.type=d.Text):b.raw=b.data=b.raw+c));if(b.type==d.Tag&&(b.name=f,f=f.toLowerCase(),0==b.raw.indexOf("!--")?(b.type=d.Comment,delete b.name,h=b.raw.length,"-"==b.raw.charAt(h- 1)&&"-"==b.raw.charAt(h-2)&&">"==c?b.raw=b.data=b.raw.replace(e._reTrimComment,""):(b.raw+=c,this._tagStack.push(d.Comment))):0==b.raw.indexOf("!")||0==b.raw.indexOf("?")?b.type=d.Directive:"script"==f?(b.type=d.Script,"/"!=b.data.charAt(b.data.length-1)&&this._tagStack.push(d.Script)):"/script"==f?b.type=d.Script:"style"==f?(b.type=d.Style,"/"!=b.data.charAt(b.data.length-1)&&this._tagStack.push(d.Style)):"/style"==f&&(b.type=d.Style),b.name&&"/"==b.name.charAt(0)))b.data=b.name;if(""!=b.raw||b.type!= d.Text)this._options.includeLocation&&!b.location&&(b.location=this.getLocation(b.type==d.Tag)),this.parseAttribs(b),this._elements.push(b),b.type!=d.Text&&b.type!=d.Comment&&b.type!=d.Directive&&"/"==b.data.charAt(b.data.length-1)&&this._elements.push({raw:"/"+b.name,data:"/"+b.name,name:"/"+b.name,type:b.type});this._parseState="<"==c?d.Tag:d.Text;this._current=this._next+1;this._prevTagSep=c}this._options.includeLocation&&(this.getLocation(),this._location.row+=this._location.inBuffer,this._location.inBuffer= 0,this._location.charOffset=0);this._buffer=this._current<=a?this._buffer.substring(this._current):"";this._current=0;this.writeHandler()};e.prototype.getLocation=function(a){for(var c=this._location,b=this._current-(a?1:0),d=a&&0==c.charOffset&&0==this._current;c.charOffset=d)return g;if(b&&c.children)c= c.children;else if(!(c instanceof Array))return g;for(i=0;i=d);i++);return g},getElementById:function(a,c,b){a=f.getElements({id:a},c,b,1);return a.length?a[0]:null},getElementsByTagName:function(a,c,b,d){return f.getElements({tag_name:a},c,b,d)},getElementsByTagType:function(a,c,b,d){return f.getElements({tag_type:a},c,b,d)}};exports.Parser=e;exports.DefaultHandler=g;exports.RssHandler=j;exports.ElementType=d;exports.DomUtils=f})(); \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/lib/node-htmlparser.js b/node_modules/jsdom/node_modules/htmlparser/lib/node-htmlparser.js new file mode 100644 index 0000000..1fc03ea --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/lib/node-htmlparser.js @@ -0,0 +1,6 @@ +var htmlparser = require("./htmlparser"); +exports.Parser = htmlparser.Parser; +exports.DefaultHandler = htmlparser.DefaultHandler; +exports.RssHandler = htmlparser.RssHandler; +exports.ElementType = htmlparser.ElementType; +exports.DomUtils = htmlparser.DomUtils; diff --git a/node_modules/jsdom/node_modules/htmlparser/lib/node-htmlparser.min.js b/node_modules/jsdom/node_modules/htmlparser/lib/node-htmlparser.min.js new file mode 100644 index 0000000..27d5eea --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/lib/node-htmlparser.min.js @@ -0,0 +1,6 @@ +var htmlparser = require("./htmlparser.min"); +exports.Parser = htmlparser.Parser; +exports.DefaultHandler = htmlparser.DefaultHandler; +exports.RssHandler = htmlparser.RssHandler; +exports.ElementType = htmlparser.ElementType; +exports.DomUtils = htmlparser.DomUtils; diff --git a/node_modules/jsdom/node_modules/htmlparser/libxmljs.node b/node_modules/jsdom/node_modules/htmlparser/libxmljs.node new file mode 100755 index 0000000..07e08c8 Binary files /dev/null and b/node_modules/jsdom/node_modules/htmlparser/libxmljs.node differ diff --git a/node_modules/jsdom/node_modules/htmlparser/new/a b/node_modules/jsdom/node_modules/htmlparser/new/a new file mode 100644 index 0000000..4506b37 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/new/a @@ -0,0 +1,6 @@ +[ +{"type":"tag","name":"script","name_raw":"script","raw":"script language='javascript'"}, +{"type":"attr","name":"langauge","name_raw":"language","value":"javascript"}, +{"type":"text","data":"\nvar foo = 'xxx';\n"}, +{"type":"tag","name":"/script","name_raw":"/script","raw":"/script"} +] diff --git a/node_modules/jsdom/node_modules/htmlparser/new/b b/node_modules/jsdom/node_modules/htmlparser/new/b new file mode 100644 index 0000000..759c80f --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/new/b @@ -0,0 +1,6 @@ +[ +{"type":"tag","name":"script","name_raw":"script","raw":"script language='javascript'"}, +{"type":"attr","name":"language","name_raw":"language","value":"javascript"}, +{"type":"text","data":"\nvar foo = 'xxx';\n"}, +{"type":"tag","name":"/script","name_raw":"/script","raw":"/script"} +] diff --git a/node_modules/jsdom/node_modules/htmlparser/new/compat.js b/node_modules/jsdom/node_modules/htmlparser/new/compat.js new file mode 100644 index 0000000..eb1f4e7 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/new/compat.js @@ -0,0 +1,954 @@ +var htmlparser_old = require('../lib/htmlparser'); +var htmlparser_new = require('./htmlparser'); + +var tests = { + + 'plain text': { + data: ['This is the text'] + , expected: [{ type: 'text', data: 'This is the text' }] + } + + , 'split text': { + data: ['This is', ' the text'] + , expected: [{ type: 'text', data: 'This is the text' }] + } + + , 'simple tag': { + data: ['
    '] + , expected: [{ type: 'tag', name: 'div', raw: 'div' }] + } + + , 'simple comment': { + data: [''] + , expected: [{ type: 'comment', data: ' content ' }] + } + + , 'simple cdata': { + data: [''] + , expected: [{ type: 'cdata', data: ' content ' }] + } + + , 'split simple tag #1': { + data: ['<', 'div>'] + , expected: [{ type: 'tag', name: 'div', raw: 'div' }] + } + + , 'split simple tag #2': { + data: [''] + , expected: [{ type: 'tag', name: 'div', raw: 'div' }] + } + + , 'split simple tag #3': { + data: [''] + , expected: [{ type: 'tag', name: 'div', raw: 'div' }] + } + + , 'text before tag': { + data: ['xxx
    '] + , expected: [ + { type: 'text', data: 'xxx'}, + { type: 'tag', name: 'div', raw: 'div' } + ] + } + + , 'text after tag': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div' }, + { type: 'text', data: 'xxx'} + ] + } + + , 'text inside tag': { + data: ['
    xxx
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div' }, + { type: 'text', data: 'xxx'}, + { type: 'tag', name: '/div', raw: '/div' } + ] + } + + , 'attribute with single quotes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=\'1\'' }, + { type: 'attr', name:'a', data: '1'} + ] + } + + , 'attribute with double quotes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a="1"' }, + { type: 'attr', name:'a', data: '1'} + ] + } + + , 'attribute with no quotes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=1' }, + { type: 'attr', name:'a', data: '1'} + ] + } + + , 'attribute with no value': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div wierd' }, + { type: 'attr', name:'wierd', data: null} + ] + } + + , 'attribute with no value, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div wierd' }, + { type: 'attr', name:'wierd', data: null}, + { type: 'text', data: 'xxx' } + ] + } + + , 'tag with multiple attributes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a="1" b="2"' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'} + ] + } + + , 'tag with multiple attributes, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a="1" b="2"' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'text', data: 'xxx' } + ] + } + + , 'tag with mixed attributes #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=1 b=\'2\' c="3"' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'} + ] + } + + , 'tag with mixed attributes #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=1 b="2" c=\'3\'' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'} + ] + } + + , 'tag with mixed attributes #3': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=\'1\' b=2 c="3"' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'} + ] + } + + , 'tag with mixed attributes #4': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=\'1\' b="2" c=3' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'} + ] + } + + , 'tag with mixed attributes #5': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a="1" b=2 c=\'3\'' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'} + ] + } + + , 'tag with mixed attributes #6': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a="1" b=\'2\' c="3"' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'} + ] + } + + , 'tag with mixed attributes, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=1 b=\'2\' c="3"' }, + { type: 'attr', name:'a', data: '1'}, + { type: 'attr', name:'b', data: '2'}, + { type: 'attr', name:'c', data: '3'}, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'self closing tag, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', raw: null }, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag with spaces #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div /' }, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'self closing tag with spaces #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div/ ' }, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'self closing tag with spaces #3': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div / ' }, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'self closing tag with spaces, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div / ' }, + { type: 'tag', name: '/div', raw: null }, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag with attribute': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=b /' }, + { type: 'attr', name:'a', data: 'b'}, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'self closing tag with attribute, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a=b /' }, + { type: 'attr', name:'a', data: 'b'}, + { type: 'tag', name: '/div', raw: null }, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag split #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'self closing tag split #2': { + data: [''] + , expected: [ + { type: 'tag', name: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', raw: null } + ] + } + + , 'attribute missing close quote': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div a="1>'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'split attribute #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'split attribute #3': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'split attribute #4': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'split attribute #5': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'split attribute #6': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'attribute split from tag #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'attribute split from tag #2': { + data: [''] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', data: 'yyy'} + ] + } + + , 'text before complex tag': { + data: ['xxx
    '] + , expected: [ + { type: 'text', data: 'xxx' }, + { type: 'tag', name: 'div', raw: 'div yyy="123"'}, + { type: 'attr', name: 'yyy', data: '123' } + ] + } + + , 'text after complex tag': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', raw: 'div yyy="123"'}, + { type: 'attr', name: 'yyy', data: '123' }, + { type: 'text', data: 'xxx' } + ] + } + + , 'text inside complex tag': { + data: ['
    xxx
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div yyy="123"'}, + { type: 'attr', name: 'yyy', data: '123' }, + { type: 'text', data: 'xxx' }, + { type: 'tag', name: '/div', raw: '/div'} + ] + } + + , 'nested tags': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div'}, + { type: 'tag', name: 'span', raw: 'span'}, + { type: 'tag', name: '/span', raw: '/span'}, + { type: 'tag', name: '/div', raw: '/div'} + ] + } + + , 'nested tags with attributes': { + data: ['
    xxx
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div aaa="bbb"'}, + { type: 'attr', name: 'aaa', data: 'bbb' }, + { type: 'tag', name: 'span', raw: 'span 123=\'456\''}, + { type: 'attr', name: '123', data: '456' }, + { type: 'text', data: 'xxx' }, + { type: 'tag', name: '/span', raw: '/span'}, + { type: 'tag', name: '/div', raw: '/div'} + ] + } + + , 'comment inside tag': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div'}, + { type: 'comment', data: ' comment text '}, + { type: 'tag', name: '/div', raw: '/div'} + ] + } + + , 'cdata inside tag': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div'}, + { type: 'cdata', data: ' CData content '}, + { type: 'tag', name: '/div', raw: '/div'} + ] + } + + , 'html inside comment': { + data: [''] + , expected: [{ type: 'comment', data: '
    foo
    '}] + } + + , 'html inside cdata': { + data: ['foo
    ]]>'] + , expected: [{ type: 'cdata', data: '
    foo
    '}] + } + + , 'quotes in attribute #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx=\'a"b\''}, + { type: 'attr', name: 'xxx', data: 'a"b' } + ] + } + + , 'quotes in attribute #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="a\'b"'}, + { type: 'attr', name: 'xxx', data: 'a\'b' } + ] + } + + , 'brackets in attribute': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', raw: 'div xxx="
    "'}, + { type: 'attr', name: 'xxx', data: '
    ' } + ] + } + + , 'split comment #1': { + data: ['<','!-- comment text -->xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #2': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #3': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #4': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #5': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #6': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #7': { + data: ['"] + , expected: [ + { type: 'comment', data: "\ncomment text\n" } + ] + } + + , 'cdata comment': { + data: [""] + , expected: [ + { type: 'cdata', data: "\nCData content\n" } + ] + } + + , 'multiline attribute #1': { + data: ["
    "] + , expected: [ + { type: 'tag', name: 'div', raw: "div id='\nxxx\nyyy\n'" }, + { type: 'attr', name: 'id', data: "\nxxx\nyyy\n" } + ] + } + + , 'multiline attribute #2': { + data: ["
    "] + , expected: [ + { type: 'tag', name: 'div', raw: "div id=\"\nxxx\nyyy\n\"" }, + { type: 'attr', name: 'id', data: "\nxxx\nyyy\n" } + ] + } + + , 'tags in script tag code': { + data: [""] + , expected: [ + { type: 'tag', name: 'script', raw: "script language='javascript'" }, + { type: 'attr', name: 'language', data: 'javascript' }, + { type: 'text', data: "\nvar foo = 'xxx';\n" }, + { type: 'tag', name: '/script', raw: "/script" }, + ] + } + + , 'closing script tag in script tag code': { + data: ["';\n"] + , expected: [ + { type: 'tag', name: 'script', raw: "script language='javascript'" }, + { type: 'attr', name: 'language', data: 'javascript' }, + { type: 'text', data: "\nvar foo = '" }, + { type: 'tag', name: '/script', raw: "/script" }, + { type: 'text', data: "';\n" }, + { type: 'tag', name: '/script', raw: "/script" } + ] + } + + , 'comment in script tag code': { + data: [""] + , expected: [ + { type: 'tag', name: 'script', raw: "script language='javascript'" }, + { type: 'attr', name: 'language', data: 'javascript' }, + { type: 'text', data: "\nvar foo = '';\n" }, + { type: 'tag', name: '/script', raw: "/script" }, + ] + } + + , 'cdata in script tag code': { + data: [""] + , expected: [ + { type: 'tag', name: 'script', raw: "script language='javascript'" }, + { type: 'attr', name: 'language', data: 'javascript' }, + { type: 'text', data: "\nvar foo = '';\n" }, + { type: 'tag', name: '/script', raw: "/script" }, + ] + } + + , 'commented script tag code': { + data: [""] + , expected: [ + { type: 'tag', name: 'script', raw: "script language='javascript'" }, + { type: 'attr', name: 'language', data: 'javascript' }, + { type: 'text', data: "\n\n" }, + { type: 'tag', name: '/script', raw: "/script" }, + ] + } + + , 'cdata in script tag': { + data: [""] + , expected: [ + { type: 'tag', name: 'script', raw: "script language='javascript'" }, + { type: 'attr', name: 'language', data: 'javascript' }, + { type: 'text', data: "\nxxx';\n]]>\n" }, + { type: 'tag', name: '/script', raw: "/script" }, + ] + } + +}; + +function runTests (permutator) { + var callback = function handlerCallback (err) { + if (err) { + console.log('Handler error', err); + } + } + var handler = new htmlparser_new.HtmlHandler(callback); + var parser = new htmlparser_new.Parser(handler); + + var passed = 0; + var failed = 0; + + console.time('Tests'); + for (var testName in tests) { + var test = permutator ? permutator(tests[testName]) : tests[testName]; + process.stdout.write('[TEST] ' + testName + ' : '); + parser.reset(); + for (var i = 0, len = test.data.length; i < len; i++) { + parser.parseChunk(test.data[i]); + } + parser.done(); + var expected = JSON.stringify(test.expected); + var result = JSON.stringify(parser.state.output); + if (expected !== result) { + failed++; + process.stdout.write("FAIL\n"); + console.log(' [EXPECTED]', expected); + console.log(' [ RESULT ]', result); + } else { + passed++; + process.stdout.write("Ok\n"); + } + } + console.timeEnd('Tests'); + console.log('Passed tests: ' + passed + '/' + (passed + failed) + ' (' + Math.round(passed / (passed + failed) * 100) + '%)'); +} + +runTests(); +runTests(function (test) { + test.data = test.data.join('').split(''); + return test; +}); + +function handlerCallback (err, dom) { + console.log(err || dom); +} + +var handlerOld = new htmlparser_old.DefaultHandler(handlerCallback); +var parserOld = new htmlparser_old.Parser(handlerOld); + +var handlerNew = new htmlparser_new.HtmlHandler(null, handlerCallback); +var parserNew = new htmlparser_new.Parser(handlerNew); +parserNew.parseComplete(''); + diff --git a/node_modules/jsdom/node_modules/htmlparser/new/htmlparser.js b/node_modules/jsdom/node_modules/htmlparser/new/htmlparser.js new file mode 100644 index 0000000..6b9bfe9 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/new/htmlparser.js @@ -0,0 +1,645 @@ +(function () { + +function runningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!runningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + else if (this.Tautologistics.NodeHtmlParser) + return; //NodeHtmlParser already defined! + this.Tautologistics.NodeHtmlParser = {}; + exports = this.Tautologistics.NodeHtmlParser; +} + +var Mode = { + Text: 'text', + Tag: 'tag', + Attr: 'attr', + CData: 'cdata', + Comment: 'comment' +}; + +var re_parseText_scriptClose = /<\s*\/\s*script/ig; +function parseText (state) { + var foundPos; + if (state.isScript) { + re_parseText_scriptClose.lastIndex = state.pos; + foundPos = re_parseText_scriptClose.exec(state.data); + foundPos = (foundPos) ? + foundPos.index + : + -1 + ; + } else { + foundPos = state.data.indexOf('<', state.pos); + } + var text = (foundPos === -1) ? state.data.substring(state.pos, state.data.length) : state.data.substring(state.pos, foundPos); + if (foundPos < 0 && state.done) { + foundPos = state.data.length; + } + if (foundPos < 0) { + if (state.isScript) { + state.needData = true; + return; + } + if (!state.pendingText) { + state.pendingText = []; + } + state.pendingText.push(state.data.substring(state.pos, state.data.length)); + state.pos = state.data.length; + } else { + if (state.pendingText) { + state.pendingText.push(state.data.substring(state.pos, foundPos)); + text = state.pendingText.join(''); + state.pendingText = null; + } else { + text = state.data.substring(state.pos, foundPos); + } + if (text !== '') { + state.output.push({ type: Mode.Text, data: text }); + } + state.pos = foundPos + 1; + state.mode = Mode.Tag; + } +} + +var re_parseTag = /\s*(\/?)\s*([^\s>\/]+)(\s*)(>?)/g; +function parseTag (state) { + re_parseTag.lastIndex = state.pos; + var match = re_parseTag.exec(state.data); + if (match) { + if (!match[1] && match[2].substr(0, 3) === '!--') { + state.mode = Mode.Comment; + state.pos += 3; + return; + } + if (!match[1] && match[2].substr(0, 8) === '![CDATA[') { + state.mode = Mode.CData; + state.pos += 8; + return; + } + if (!state.done && (state.pos + match[0].length) === state.data.length) { + //We're at the and of the data, might be incomplete + state.needData = true; + return; + } + var raw; + if (match[4] === '>') { + state.mode = Mode.Text; + raw = match[0].substr(0, match[0].length - 1); + } else { + state.mode = Mode.Attr; + raw = match[0]; + } + state.pos += match[0].length; + var tag = { type: Mode.Tag, name: match[1] + match[2], raw: raw }; + if (state.mode === Mode.Attr) { + state.lastTag = tag; + } + if (tag.name.toLowerCase() === 'script') { + state.isScript = true; + } else if (tag.name.toLowerCase() === '/script') { + state.isScript = false; + } + state.output.push(tag); + } else { + //TODO: end of tag? + //TODO: push to pending? + state.needData = true; + } +} + +var re_parseAttr_findName = /\s*([^=<>\s'"\/]+)\s*/g; +function parseAttr_findName (state) { + re_parseAttr_findName.lastIndex = state.pos; + var match = re_parseAttr_findName.exec(state.data); + if (!match) { + return null; + } + if (state.pos + match[0].length !== re_parseAttr_findName.lastIndex) { + return null; + } + return { + match: match[0] + , name: match[1] + }; +} +var re_parseAttr_findValue = /\s*=\s*(?:'([^']*)'|"([^"]*)"|([^'"\s\/>]+))\s*/g; +var re_parseAttr_findValue_last = /\s*=\s*['"]?(.*)$/g; +function parseAttr_findValue (state) { + re_parseAttr_findValue.lastIndex = state.pos; + var match = re_parseAttr_findValue.exec(state.data); + if (!match) { + if (!state.done) { + return null; + } + re_parseAttr_findValue_last.lastIndex = state.pos; + match = re_parseAttr_findValue_last.exec(state.data); + if (!match) { + return null; + } + return { + match: match[0] + , value: (match[1] !== '') ? match[1] : null + }; + } + if (state.pos + match[0].length !== re_parseAttr_findValue.lastIndex) { + return null; + } + return { + match: match[0] + , value: match[1] || match[2] || match[3] + }; +} +var re_parseAttr_splitValue = /\s*=\s*['"]?/g; +var re_parseAttr_selfClose = /(\s*\/\s*)(>?)/g; +function parseAttr (state) { + var name_data = parseAttr_findName(state); + if (!name_data) { + re_parseAttr_selfClose.lastIndex = state.pos; + var matchTrailingSlash = re_parseAttr_selfClose.exec(state.data); + if (matchTrailingSlash && matchTrailingSlash.index === state.pos) { + if (!state.done && !matchTrailingSlash[2] && state.pos + matchTrailingSlash[0].length === state.data.length) { + state.needData = true; + return; + } + state.lastTag.raw += matchTrailingSlash[1]; + state.output.push({ type: Mode.Tag, name: '/' + state.lastTag.name, raw: null }); + state.pos += matchTrailingSlash[1].length; + } + var foundPos = state.data.indexOf('>', state.pos); + if (foundPos < 0) { + if (state.done) { //TODO: is this needed? + state.lastTag.raw += state.data.substr(state.pos); + state.pos = state.data.length; + return; + } + state.needData = true; + } else { + // state.lastTag = null; + state.pos = foundPos + 1; + state.mode = Mode.Text; + } + return; + } + if (!state.done && state.pos + name_data.match.length === state.data.length) { + state.needData = true; + return null; + } + state.pos += name_data.match.length; + var value_data = parseAttr_findValue(state); + if (value_data) { + if (!state.done && state.pos + value_data.match.length === state.data.length) { + state.needData = true; + state.pos -= name_data.match.length; + return; + } + state.pos += value_data.match.length; + } else { + re_parseAttr_splitValue.lastIndex = state.pos; + if (re_parseAttr_splitValue.exec(state.data)) { + state.needData = true; + state.pos -= name_data.match.length; + return; + } + value_data = { + match: '' + , value: null + }; + } + state.lastTag.raw += name_data.match + value_data.match; + + state.output.push({ type: Mode.Attr, name: name_data.name, data: value_data.value }); +} + +var re_parseCData_findEnding = /\]{1,2}$/; +function parseCData (state) { + var foundPos = state.data.indexOf(']]>', state.pos); + if (foundPos < 0 && state.done) { + foundPos = state.data.length; + } + if (foundPos < 0) { + re_parseCData_findEnding.lastIndex = state.pos; + var matchPartialCDataEnd = re_parseCData_findEnding.exec(state.data); + if (matchPartialCDataEnd) { + state.needData = true; + return; + } + if (!state.pendingText) { + state.pendingText = []; + } + state.pendingText.push(state.data.substr(state.pos, state.data.length)); + state.pos = state.data.length; + state.needData = true; + } else { + var text; + if (state.pendingText) { + state.pendingText.push(state.data.substring(state.pos, foundPos)); + text = state.pendingText.join(''); + state.pendingText = null; + } else { + text = state.data.substring(state.pos, foundPos); + } + state.output.push({ type: Mode.CData, data: text }); + state.mode = Mode.Text; + state.pos = foundPos + 3; + } +} + +var re_parseComment_findEnding = /\-{1,2}$/; +function parseComment (state) { + var foundPos = state.data.indexOf('-->', state.pos); + if (foundPos < 0 && state.done) { + foundPos = state.data.length; + } + if (foundPos < 0) { + re_parseComment_findEnding.lastIndex = state.pos; + var matchPartialCommentEnd = re_parseComment_findEnding.exec(state.data); + if (matchPartialCommentEnd) { + state.needData = true; + return; + } + if (!state.pendingText) { + state.pendingText = []; + } + state.pendingText.push(state.data.substr(state.pos, state.data.length)); + state.pos = state.data.length; + state.needData = true; + } else { + var text; + if (state.pendingText) { + state.pendingText.push(state.data.substring(state.pos, foundPos)); + text = state.pendingText.join(''); + state.pendingText = null; + } else { + text = state.data.substring(state.pos, foundPos); + } + state.output.push({ type: Mode.Comment, data: text }); + state.mode = Mode.Text; + state.pos = foundPos + 3; + } +} + +function parse (state) { + switch (state.mode) { + case Mode.Text: + return parseText(state); + case Mode.Tag: + return parseTag(state); + case Mode.Attr: + return parseAttr(state); + case Mode.CData: + return parseCData(state); + case Mode.Comment: + return parseComment(state); + } +} + +function Parser (handler, options) { + this._options = options ? options : { }; + if (this._options.includeLocation == undefined) { + this._options.includeLocation = false; //Do not track element position in document by default + } + + this.validateHandler(handler); + var self = this; + this._handler = handler; + this.reset(); +} + + Parser.prototype.reset = function Parser$reset () { + this.state = { + mode: Mode.Text, + pos: 0, + data: null, + pendingText: null, + lastTag: null, + isScript: false, + needData: false, + // output: [], + done: false + }; + }; + + Parser.prototype.parseChunk = function Parser$parseChunk (chunk) { + this.state.needData = false; + this.state.data = (this.state.data !== null) ? + this.state.data.substr(this.pos) + chunk + : + chunk + ; + while (this.state.pos < this.state.data.length && !this.state.needData) { + parse(this.state); + } + }; + + Parser.prototype.parseComplete = function Parser$parseComplete (data) { + this.reset(); + this.parseChunk(data); + this.done(); + } + + Parser.prototype.done = function Parser$done () { + this.state.done = true; + parse(this.state); + + }; + + Parser.prototype.validateHandler = function Parser$validateHandler (handler) { + if ((typeof handler) != "object") { + throw new Error("Handler is not an object"); + } + if ((typeof handler.reset) != "function") { + throw new Error("Handler method 'reset' is invalid"); + } + if ((typeof handler.done) != "function") { + throw new Error("Handler method 'done' is invalid"); + } + if ((typeof handler.write) != "function") { + throw new Error("Handler method 'write' is invalid"); + } + if ((typeof handler.error) != "function") { + throw new Error("Handler method 'error' is invalid"); + } + } + +// Parser.prototype.done_old = function Parser$done_old () { +// if (this.state.pendingText) { +// this.state.output.push({ type: this.state.mode, data: this.state.pendingText.join('') }); +// this.state.pendingText = null; +// } +// console.log(this.state); + +// var buffer = []; +// var lastType; +// for (var i = 0, len = this.state.output.length; i < len; i++) { +// var node = this.state.output[i]; +// if ((lastType === Mode.Attr && node.type !== Mode.Attr) || (lastType === Mode.Tag && node.type !== Mode.Attr)) { +// buffer.push('>'); +// } +// switch (node.type) { + +// case Mode.Text: +// buffer.push(node.data); +// break; + +// case Mode.Comment: +// buffer.push(''); +// break; + +// case Mode.CData: +// buffer.push(''); +// break; + +// case Mode.Tag: +// buffer.push('<', node.name); +// break; + +// case Mode.Attr: +// var quoteChar = (node.value.indexOf('\'') < 0) ? '\'' : '"'; +// buffer.push(' ', node.name, '=', quoteChar, node.value, quoteChar); +// break; + +// } +// lastType = node.type; +// } +// if (lastType === Mode.Tag || lastType === Mode.Attr) { +// buffer.push('>'); +// } +// console.log(buffer.join('')); +// }; + +function HtmlHandler (options, callback) { + this.reset(); + this._options = options ? options : { }; + if (this._options.ignoreWhitespace == undefined) { + this._options.ignoreWhitespace = false; //Keep whitespace-only text nodes + } + if (this._options.trackPosition == undefined) { + this._options.trackPosition = false; //Include position of element (row, col) on nodes + } + if (this._options.verbose == undefined) { + this._options.verbose = true; //Keep data property for tags and raw property for all + } + if (this._options.enforceEmptyTags == undefined) { + this._options.enforceEmptyTags = true; //Don't allow children for HTML tags defined as empty in spec + } + if (this._options.caseSensitiveTags == undefined) { + this._options.caseSensitiveTags = false; //Lowercase all tag names + } + if (this._options.caseSensitiveAttr == undefined) { + this._options.caseSensitiveAttr = false; //Lowercase all attribute names + } + if ((typeof callback) == "function") { + this._callback = callback; + } +} + + //**"Static"**// + //HTML Tags that shouldn't contain child nodes + HtmlHandler._emptyTags = { + area: 1 + , base: 1 + , basefont: 1 + , br: 1 + , col: 1 + , frame: 1 + , hr: 1 + , img: 1 + , input: 1 + , isindex: 1 + , link: 1 + , meta: 1 + , param: 1 + , embed: 1 + } + //Regex to detect whitespace only text nodes + HtmlHandler.reWhitespace = /^\s*$/; + + //**Public**// + //Properties// + HtmlHandler.prototype.dom = null; //The hierarchical object containing the parsed HTML + //Methods// + //Resets the handler back to starting state + HtmlHandler.prototype.reset = function HtmlHandler$reset() { + this.dom = []; + this._done = false; + this._tagStack = []; + this._tagStack.last = function HtmlHandler$_tagStack$last () { + return(this.length ? this[this.length - 1] : null); + } + } + //Signals the handler that parsing is done + HtmlHandler.prototype.done = function HtmlHandler$done () { + this._done = true; + this.handleCallback(null); + } + + HtmlHandler.prototype.error = function HtmlHandler$error (error) { + this.handleCallback(error); + } + + HtmlHandler.prototype.handleCallback = function HtmlHandler$handleCallback (error) { + if ((typeof this._callback) != "function") + if (error) + throw error; + else + return; + this._callback(error, this.dom); + } + + HtmlHandler.prototype.isEmptyTag = function HtmlHandler$isEmptyTag (element) { + var name = element.name.toLowerCase(); + if (name.charAt(0) == '/') { + name = name.substring(1); + } + return this._options.enforceEmptyTags && !!HtmlHandler._emptyTags[name]; + }; + + HtmlHandler.prototype._copyElement = function HtmlHandler$_copyElement (element) { + var newElement = { type: element.type }; + + if (this._options.verbose && element['raw'] !== undefined) { + newElement.raw = element.raw; + } + if (element['name'] !== undefined) { + switch (element.type) { + + case Mode.Tag: + newElement.name = this._options.caseSensitiveTags ? + element.name + : + element.name.toLowerCase() + ; + break; + + case Mode.Attr: + newElement.name = this._options.caseSensitiveAttr ? + element.name + : + element.name.toLowerCase() + ; + break; + + default: + newElement.name = this._options.caseSensitiveTags ? + element.name + : + element.name.toLowerCase() + ; + break; + + } + } + if (element['data'] !== undefined) { + newElement.data = element.name; + } + + return newElement; + } + + HtmlHandler.prototype.write = function HtmlHandler$write (element) { + if (this._done) { + this.handleCallback(new Error("Writing to the handler after done() called is not allowed without a reset()")); + } + if (element.type === Mode.Text && this._options.ignoreWhitespace) { + if (HtmlHandler.reWhitespace.test(element.data)) { + return; + } + } + var node; + if (!this._options.verbose) { +// element.raw = null; //FIXME: Not clean + //FIXME: Serious performance problem using delete + delete element.raw; + if (element.type == "tag" || element.type == "script" || element.type == "style") { + delete element.data; + } + } + if (!this._tagStack.last()) { //There are no parent elements + //If the element can be a container, add it to the tag stack and the top level list + if (element.type != Mode.Text && element.type != Mode.Comment && element.type != Mode.CData) { + if (element.name.charAt(0) != "/") { //Ignore closing tags that obviously don't have an opening tag + node = this._copyElement(element); + this.dom.push(node); + if (!this.isEmptyTag(node)) { //Don't add tags to the tag stack that can't have children + this._tagStack.push(node); + } + } + } + else //Otherwise just add to the top level list + this.dom.push(this._copyElement(element)); + } + else { //There are parent elements + //If the element can be a container, add it as a child of the element + //on top of the tag stack and then add it to the tag stack + if (element.type != Mode.Text && element.type != Mode.Comment && element.type != Mode.CData) { + if (element.name.charAt(0) == "/") { + //This is a closing tag, scan the tagStack to find the matching opening tag + //and pop the stack up to the opening tag's parent + var baseName = this._options.caseSensitiveTags ? + element.name.substring(1) + : + element.name.substring(1).toLowerCase() + ; + if (!this.isEmptyTag(element)) { + var pos = this._tagStack.length - 1; + while (pos > -1 && this._tagStack[pos--].name != baseName) { } + if (pos > -1 || this._tagStack[0].name == baseName) { + while (pos < this._tagStack.length - 1) { + this._tagStack.pop(); + } + } + } + } + else { //This is not a closing tag + if (!this._tagStack.last().children) { + this._tagStack.last().children = []; + } + node = this._copyElement(element); + this._tagStack.last().children.push(node); + if (!this.isEmptyTag(node)) { //Don't add tags to the tag stack that can't have children + this._tagStack.push(node); + } + } + } + else { //This is not a container element + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(this._copyElement(element)); + } + } + } + + + //**Private**// + //Properties// + HtmlHandler.prototype._options = null; //Handler options for how to behave + HtmlHandler.prototype._callback = null; //Callback to respond to when parsing done + HtmlHandler.prototype._done = false; //Flag indicating whether handler has been notified of parsing completed + HtmlHandler.prototype._tagStack = null; //List of parents to the currently element being processed + //Methods// + +exports.Parser = Parser; + +exports.HtmlHandler = HtmlHandler; + +// exports.RssHandler = RssHandler; + +exports.ElementType = Mode; + +// exports.DomUtils = DomUtils; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/new/parser.zip b/node_modules/jsdom/node_modules/htmlparser/new/parser.zip new file mode 100644 index 0000000..c562a64 Binary files /dev/null and b/node_modules/jsdom/node_modules/htmlparser/new/parser.zip differ diff --git a/node_modules/jsdom/node_modules/htmlparser/new/test01.js b/node_modules/jsdom/node_modules/htmlparser/new/test01.js new file mode 100644 index 0000000..3582584 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/new/test01.js @@ -0,0 +1,258 @@ +var data = "\ +starting text\n\ +aaabbb\n\ +\n\ +< htmL >\n\ + \n\ +
    \n\ +
    xxx
    \n\ +
    yyyyyyyyyyyy
    \n\ +
    zzzz zzz
    \n\ +
    aaaa
    \n\ + \n\ +\n\ +ending text\ +]+)(\s*)(>?)/g; +function parseTag (state) { + // console.log('parseTag', state); + // console.log('parseTag'); + re_parseTag.lastIndex = state.pos; + var match = re_parseTag.exec(state.data); + if (match) { + if (match[2].substr(0, 3) === '!--') { + state.mode = Mode.Comment; + state.pos += 3; + return; + } + if (match[2].substr(0, 8) === '![CDATA[') { + state.mode = Mode.CData; + state.pos += 8; + return; + } + var raw; + if (match[4] === '>') { + state.mode = Mode.Text; + raw = match[0].substr(0, match[0].length - 1); + } else { + state.mode = Mode.Attr; + raw = match[0]; + } + state.pos += match[0].length; + var tag = { type: Mode.Tag, name: match[2].toLowerCase(), name_raw: match[2], raw: raw }; + if (state.mode === Mode.Attr) { + state.lastTag = tag; + } + state.output.push(tag); + } else { + //TODO: end of tag? + //TODO: push to pending? + state.needData = true; + } +} + +var re_parseAttr_findName = /\s*([^=<>\s'"]+)\s*/g; +function parseAttr_findName (state) { + re_parseAttr_findName.lastIndex = state.pos; + var match = re_parseAttr_findName.exec(state.data); + if (!match) { + return null; + } + if (state.pos + match[0].length !== re_parseAttr_findName.lastIndex) { + return null; + } + state.pos += match[0].length; + state.lastTag.raw += match[0]; + return match[1]; +} +var re_parseAttr_findValue = /\s*=\s*(?:'([^']*)'|"([^"]*)"|([^'"\s>]*))/g; +function parseAttr_findValue (state) { + re_parseAttr_findValue.lastIndex = state.pos; + var match = re_parseAttr_findValue.exec(state.data); + if (!match) { + return null; + } + if (state.pos + match[0].length !== re_parseAttr_findValue.lastIndex) { + return null; + } + state.pos += match[0].length; + state.lastTag.raw += match[0]; + return match[1] || match[2] || match[3]; +}; +function parseAttr (state) { + // console.log('parseAttr', state); + // console.log('parseAttr'); + var name = parseAttr_findName(state); + if (!name) { + var foundPos = state.data.indexOf('>', state.pos); + if (foundPos < 0) { + state.needData = true; + } else { + state.lastTag = null; + state.pos = foundPos + 1; + state.mode = Mode.Text; + } + return; + } + state.output.push({ type: Mode.Attr, name: name, name_raw: name.toLowerCase(), value: parseAttr_findValue(state) }); +} + +function parseCData (state) { + // console.log('parseCData', state); + // console.log('parseCData'); + var foundPos = state.data.indexOf(']]>', state.pos); + if (foundPos < 0) { + if (!state.pendingText) { + state.pendingText = []; + } + state.pendingText.push(state.data.substr(state.pos, state.data.length)); + state.pos = state.data.length; + state.needData = true; + } else { + var text; + if (state.pendingText) { + state.pendingText.push(state.data.substring(state.pos, foundPos)); + text = state.pendingText.join(''); + state.pendingText = null; + } else { + text = state.data.substring(state.pos, foundPos); + } + state.output.push({ type: Mode.CData, data: text }); + state.mode = Mode.Text; + state.pos = foundPos + 3; + } +} + +function parseComment (state) { + // console.log('parseComment', state); + // console.log('parseComment'); + var foundPos = state.data.indexOf('-->', state.pos); + if (foundPos < 0) { + if (!state.pendingText) { + state.pendingText = []; + } + state.pendingText.push(state.data.substr(state.pos, state.data.length)); + state.pos = state.data.length; + state.needData = true; + } else { + var text; + if (state.pendingText) { + state.pendingText.push(state.data.substring(state.pos, foundPos)); + text = state.pendingText.join(''); + state.pendingText = null; + } else { + text = state.data.substring(state.pos, foundPos); + } + state.output.push({ type: Mode.Comment, data: text }); + state.mode = Mode.Text; + state.pos = foundPos + 3; + } +} + +while (state.pos < state.data.length && !state.needData) { + parse(state); +} +if (state.pendingText) { + state.output.push({ type: state.mode, data: state.pendingText }); + state.pendingText = null; +} +console.log(state); + +var buffer = []; +var lastType; +for (var i = 0, len = state.output.length; i < len; i++) { + var node = state.output[i]; + if ((lastType === Mode.Attr && node.type !== Mode.Attr) || (lastType === Mode.Tag && node.type !== Mode.Attr)) { + buffer.push('>'); + } + switch (node.type) { + + case Mode.Text: + buffer.push(node.data); + break; + + case Mode.Comment: + buffer.push(''); + break; + + case Mode.CData: + buffer.push(''); + break; + + case Mode.Tag: + buffer.push('<', node.name); + break; + + case Mode.Attr: + var quoteChar = (node.value.indexOf('\'') < 0) ? '\'' : '"'; + buffer.push(' ', node.name, '=', quoteChar, node.value, quoteChar); + break; + + } + lastType = node.type; +} +if (lastType === Mode.Tag || lastType === Mode.Attr) { + buffer.push('>'); +} +console.log(buffer.join('')); diff --git a/node_modules/jsdom/node_modules/htmlparser/new/test02.js b/node_modules/jsdom/node_modules/htmlparser/new/test02.js new file mode 100644 index 0000000..6221c95 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/new/test02.js @@ -0,0 +1,856 @@ +var htmlparser = require('./htmlparser'); + +var tests = { + + 'plain text': { + data: ['This is the text'] + , expected: [{ type: 'text', data: 'This is the text' }] + } + + , 'split text': { + data: ['This is', ' the text'] + , expected: [{ type: 'text', data: 'This is the text' }] + } + + , 'simple tag': { + data: ['
    '] + , expected: [{ type: 'tag', name: 'div', name_raw: 'div', raw: 'div' }] + } + + , 'simple comment': { + data: [''] + , expected: [{ type: 'comment', data: ' content ' }] + } + + , 'simple cdata': { + data: [''] + , expected: [{ type: 'cdata', data: ' content ' }] + } + + , 'split simple tag #1': { + data: ['<', 'div>'] + , expected: [{ type: 'tag', name: 'div', name_raw: 'div', raw: 'div' }] + } + + , 'split simple tag #2': { + data: [''] + , expected: [{ type: 'tag', name: 'div', name_raw: 'div', raw: 'div' }] + } + + , 'split simple tag #3': { + data: [''] + , expected: [{ type: 'tag', name: 'div', name_raw: 'div', raw: 'div' }] + } + + , 'text before tag': { + data: ['xxx
    '] + , expected: [ + { type: 'text', data: 'xxx'}, + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div' } + ] + } + + , 'text after tag': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div' }, + { type: 'text', data: 'xxx'} + ] + } + + , 'text inside tag': { + data: ['
    xxx
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div' }, + { type: 'text', data: 'xxx'}, + { type: 'tag', name: '/div', name_raw: '/div', raw: '/div' } + ] + } + + , 'attribute with single quotes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=\'1\'' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'} + ] + } + + , 'attribute with double quotes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a="1"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'} + ] + } + + , 'attribute with no quotes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=1' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'} + ] + } + + , 'attribute with no value': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div wierd' }, + { type: 'attr', name:'wierd', name_raw: 'wierd', value: null} + ] + } + + , 'attribute with no value, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div wierd' }, + { type: 'attr', name:'wierd', name_raw: 'wierd', value: null}, + { type: 'text', data: 'xxx' } + ] + } + + , 'tag with multiple attributes': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a="1" b="2"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'} + ] + } + + , 'tag with multiple attributes, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a="1" b="2"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'text', data: 'xxx' } + ] + } + + , 'tag with mixed attributes #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=1 b=\'2\' c="3"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'} + ] + } + + , 'tag with mixed attributes #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=1 b="2" c=\'3\'' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'} + ] + } + + , 'tag with mixed attributes #3': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=\'1\' b=2 c="3"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'} + ] + } + + , 'tag with mixed attributes #4': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=\'1\' b="2" c=3' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'} + ] + } + + , 'tag with mixed attributes #5': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a="1" b=2 c=\'3\'' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'} + ] + } + + , 'tag with mixed attributes #6': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a="1" b=\'2\' c="3"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'} + ] + } + + , 'tag with mixed attributes, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=1 b=\'2\' c="3"' }, + { type: 'attr', name:'a', name_raw: 'a', value: '1'}, + { type: 'attr', name:'b', name_raw: 'b', value: '2'}, + { type: 'attr', name:'c', name_raw: 'c', value: '3'}, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'self closing tag, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null }, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag with spaces #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div /' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'self closing tag with spaces #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div/ ' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'self closing tag with spaces #3': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div / ' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'self closing tag with spaces, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div / ' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null }, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag with attribute': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=b /' }, + { type: 'attr', name:'a', name_raw: 'a', value: 'b'}, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'self closing tag with attribute, trailing text': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a=b /' }, + { type: 'attr', name:'a', name_raw: 'a', value: 'b'}, + { type: 'tag', name: '/div', name_raw: '/div', raw: null }, + { type: 'text', data: 'xxx' } + ] + } + + , 'self closing tag split #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'self closing tag split #2': { + data: [''] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div/' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: null } + ] + } + + , 'attribute missing close quote': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div a="1>'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'split attribute #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'split attribute #3': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'split attribute #4': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'split attribute #5': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'split attribute #6': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'attribute split from tag #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'attribute split from tag #2': { + data: [''] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="yyy"' }, + { type: 'attr', name:'xxx', name_raw: 'xxx', value: 'yyy'} + ] + } + + , 'text before complex tag': { + data: ['xxx
    '] + , expected: [ + { type: 'text', data: 'xxx' }, + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div yyy="123"'}, + { type: 'attr', name: 'yyy', name_raw: 'yyy', value: '123' } + ] + } + + , 'text after complex tag': { + data: ['
    xxx'] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div yyy="123"'}, + { type: 'attr', name: 'yyy', name_raw: 'yyy', value: '123' }, + { type: 'text', data: 'xxx' } + ] + } + + , 'text inside complex tag': { + data: ['
    xxx
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div yyy="123"'}, + { type: 'attr', name: 'yyy', name_raw: 'yyy', value: '123' }, + { type: 'text', data: 'xxx' }, + { type: 'tag', name: '/div', name_raw: '/div', raw: '/div'} + ] + } + + , 'nested tags': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div'}, + { type: 'tag', name: 'span', name_raw: 'span', raw: 'span'}, + { type: 'tag', name: '/span', name_raw: '/span', raw: '/span'}, + { type: 'tag', name: '/div', name_raw: '/div', raw: '/div'} + ] + } + + , 'nested tags with attributes': { + data: ['
    xxx
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div aaa="bbb"'}, + { type: 'attr', name: 'aaa', name_raw: 'aaa', value: 'bbb' }, + { type: 'tag', name: 'span', name_raw: 'span', raw: 'span 123=\'456\''}, + { type: 'attr', name: '123', name_raw: '123', value: '456' }, + { type: 'text', data: 'xxx' }, + { type: 'tag', name: '/span', name_raw: '/span', raw: '/span'}, + { type: 'tag', name: '/div', name_raw: '/div', raw: '/div'} + ] + } + + , 'comment inside tag': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div'}, + { type: 'comment', data: ' comment text '}, + { type: 'tag', name: '/div', name_raw: '/div', raw: '/div'} + ] + } + + , 'cdata inside tag': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div'}, + { type: 'cdata', data: ' CData content '}, + { type: 'tag', name: '/div', name_raw: '/div', raw: '/div'} + ] + } + + , 'html inside comment': { + data: [''] + , expected: [{ type: 'comment', data: '
    foo
    '}] + } + + , 'html inside cdata': { + data: ['foo
    ]]>'] + , expected: [{ type: 'cdata', data: '
    foo
    '}] + } + + , 'quotes in attribute #1': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx=\'a"b\''}, + { type: 'attr', name: 'xxx', name_raw: 'xxx', value: 'a"b' } + ] + } + + , 'quotes in attribute #2': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="a\'b"'}, + { type: 'attr', name: 'xxx', name_raw: 'xxx', value: 'a\'b' } + ] + } + + , 'brackets in attribute': { + data: ['
    '] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: 'div xxx="
    "'}, + { type: 'attr', name: 'xxx', name_raw: 'xxx', value: '
    ' } + ] + } + + , 'split comment #1': { + data: ['<','!-- comment text -->xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #2': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #3': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #4': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #5': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #6': { + data: ['xxx'] + , expected: [ + { type: 'comment', data: ' comment text '}, + { type: 'text', data: 'xxx' } + ] + } + + , 'split comment #7': { + data: ['"] + , expected: [ + { type: 'comment', data: "\ncomment text\n" } + ] + } + + , 'cdata comment': { + data: [""] + , expected: [ + { type: 'cdata', data: "\nCData content\n" } + ] + } + + , 'multiline attribute #1': { + data: ["
    "] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: "div id='\nxxx\nyyy\n'" }, + { type: 'attr', name: 'id', name_raw: 'id', value: "\nxxx\nyyy\n" } + ] + } + + , 'multiline attribute #2': { + data: ["
    "] + , expected: [ + { type: 'tag', name: 'div', name_raw: 'div', raw: "div id=\"\nxxx\nyyy\n\"" }, + { type: 'attr', name: 'id', name_raw: 'id', value: "\nxxx\nyyy\n" } + ] + } + + // script tags + // style tags + +}; + +function runTests (permutator) { + var parser = new htmlparser(); + + var passed = 0; + var failed = 0; + + console.time('Tests'); + for (var testName in tests) { + var test = permutator ? permutator(tests[testName]) : tests[testName]; + process.stdout.write('[TEST] ' + testName + ' : '); + parser.reset(); + for (var i = 0, len = test.data.length; i < len; i++) { + parser.parse(test.data[i]); + } + parser.done(); + var expected = JSON.stringify(test.expected); + var result = JSON.stringify(parser.state.output); + if (expected !== result) { + failed++; + process.stdout.write("FAIL\n"); + console.log(' [EXPECTED]', expected); + console.log(' [ RESULT ]', result); + } else { + passed++; + process.stdout.write("Ok\n"); + } + } + console.timeEnd('Tests'); + console.log('Passed tests: ' + passed + '/' + (passed + failed) + ' (' + Math.round(passed / (passed + failed) * 100) + '%)'); +} + +runTests(); +runTests(function (test) { + test.data = test.data.join('').split(''); + return test; +}); diff --git a/node_modules/jsdom/node_modules/htmlparser/newparser.js b/node_modules/jsdom/node_modules/htmlparser/newparser.js new file mode 100644 index 0000000..2487f23 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/newparser.js @@ -0,0 +1,54 @@ +//node --prof --prof_auto profile.js +//deps/v8/tools/mac-tick-processor v8.log +var sys = require("sys"); +var fs = require("fs"); + +var testHtml = "./testdata/api.html"; //Test HTML file to load +var testIterations = 100; //Number of test loops to run + +var html = fs.readFileSync(testHtml).toString(); + +function getMillisecs () { + return((new Date()).getTime()); +} + +function timeExecutions (loops, func) { + var start = getMillisecs(); + + while (loops--) + func(); + + return(getMillisecs() - start); +} + +sys.puts("HTML Length: " + html.length); + +sys.puts("Test 1: " + timeExecutions(testIterations, function () { +// function parseText (data) { +// // +// } +// function parseTag (data) { +// // +// } +// function parseAttrib (data) { +// // +// } +// function parseComment (data) { +// // +// } + var data = html.split(""); + data.meta = { + length: data.length + , pos: 0 + } + while (data.meta.length > data.meta.pos && data[data.meta.pos++] !== ""); +// sys.puts("Found: " + [data.meta.pos, data[data.meta.pos]]); +}) + "ms"); + +sys.puts("Test 2: " + timeExecutions(testIterations, function () { + var data = html; + var dataLen = data.length; + var pos = 0; + while (dataLen > pos && data.charAt(pos++) !== ""); +// sys.puts("Found: " + [pos, data.charAt(pos)]); +}) + "ms"); diff --git a/node_modules/jsdom/node_modules/htmlparser/node-htmlparser.old.js b/node_modules/jsdom/node_modules/htmlparser/node-htmlparser.old.js new file mode 100644 index 0000000..cfc1664 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/node-htmlparser.old.js @@ -0,0 +1,754 @@ +/*********************************************** +Copyright 2010, Chris Winberry . All rights reserved. +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. +***********************************************/ +/* v1.5.0 */ + +(function () { + +function runningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!runningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + else if (this.Tautologistics.NodeHtmlParser) + return; //NodeHtmlParser already defined! + this.Tautologistics.NodeHtmlParser = {}; + exports = this.Tautologistics.NodeHtmlParser; +} + +//Types of elements found in the DOM +var ElementType = { + Text: "text" //Plain text + , Directive: "directive" //Special tag + , Comment: "comment" //Special tag + , Script: "script" //Special tag + , Style: "style" //Special tag + , Tag: "tag" //Any tag that isn't special +} + +function Parser (handler) { + this.validateHandler(handler); + this._handler = handler; + this.reset(); +} + + //**"Static"**// + //Regular expressions used for cleaning up and parsing (stateless) + Parser._reTrim = /(^\s+|\s+$)/g; //Trim leading/trailing whitespace + Parser._reTrimComment = /(^\!--|--$)/g; //Remove comment tag markup from comment contents + Parser._reWhitespace = /\s/g; //Used to find any whitespace to split on + Parser._reTagName = /^\s*(\/?)\s*([^\s\/]+)/; //Used to find the tag name for an element + + //Regular expressions used for parsing (stateful) + Parser._reAttrib = //Find attributes in a tag + /([^=<>\"\'\s]+)\s*=\s*"([^"]*)"|([^=<>\"\'\s]+)\s*=\s*'([^']*)'|([^=<>\"\'\s]+)\s*=\s*([^'"\s]+)|([^=<>\"\'\s\/]+)/g; + Parser._reTags = /[\<\>]/g; //Find tag markers + + //**Public**// + //Methods// + //Parses a complete HTML and pushes it to the handler + Parser.prototype.parseComplete = function Parser$parseComplete (data) { + this.reset(); + this.parseChunk(data); + this.done(); + } + + //Parses a piece of an HTML document + Parser.prototype.parseChunk = function Parser$parseChunk (data) { + if (this._done) + this.handleError(new Error("Attempted to parse chunk after parsing already done")); + this._buffer += data; //FIXME: this can be a bottleneck + this.parseTags(); + } + + //Tells the parser that the HTML being parsed is complete + Parser.prototype.done = function Parser$done () { + if (this._done) + return; + this._done = true; + + //Push any unparsed text into a final element in the element list + if (this._buffer.length) { + var rawData = this._buffer; + this._buffer = ""; + var element = { + raw: rawData + , data: (this._parseState == ElementType.Text) ? rawData : rawData.replace(Parser._reTrim, "") + , type: this._parseState + }; + if (this._parseState == ElementType.Tag || this._parseState == ElementType.Script || this._parseState == ElementType.Style) + element.name = this.parseTagName(element.data); + this.parseAttribs(element); + this._elements.push(element); + } + + this.writeHandler(); + this._handler.done(); + } + + //Resets the parser to a blank state, ready to parse a new HTML document + Parser.prototype.reset = function Parser$reset () { + this._buffer = ""; + this._done = false; + this._elements = []; + this._elementsCurrent = 0; + this._current = 0; + this._next = 0; + this._parseState = ElementType.Text; + this._prevTagSep = ''; + this._tagStack = []; + this._handler.reset(); + } + + //**Private**// + //Properties// + Parser.prototype._handler = null; //Handler for parsed elements + Parser.prototype._buffer = null; //Buffer of unparsed data + Parser.prototype._done = false; //Flag indicating whether parsing is done + Parser.prototype._elements = null; //Array of parsed elements + Parser.prototype._elementsCurrent = 0; //Pointer to last element in _elements that has been processed + Parser.prototype._current = 0; //Position in data that has already been parsed + Parser.prototype._next = 0; //Position in data of the next tag marker (<>) + Parser.prototype._parseState = ElementType.Text; //Current type of element being parsed + Parser.prototype._prevTagSep = ''; //Previous tag marker found + //Stack of element types previously encountered; keeps track of when + //parsing occurs inside a script/comment/style tag + Parser.prototype._tagStack = null; + + //Methods// + //Takes an array of elements and parses any found attributes + Parser.prototype.parseTagAttribs = function Parser$parseTagAttribs (elements) { + var idxEnd = elements.length; + var idx = 0; + + while (idx < idxEnd) { + var element = elements[idx++]; + if (element.type == ElementType.Tag || element.type == ElementType.Script || element.type == ElementType.style) + this.parseAttribs(element); + } + + return(elements); + } + + //Takes an element and adds an "attribs" property for any element attributes found + Parser.prototype.parseAttribs = function Parser$parseAttribs (element) { + //Only parse attributes for tags + if (element.type != ElementType.Script && element.type != ElementType.Style && element.type != ElementType.Tag) + return; + + var tagName = element.data.split(Parser._reWhitespace, 1)[0]; + var attribRaw = element.data.substring(tagName.length); + if (attribRaw.length < 1) + return; + + var match; + Parser._reAttrib.lastIndex = 0; + while (match = Parser._reAttrib.exec(attribRaw)) { + if (element.attribs == undefined) + element.attribs = {}; + + if (typeof match[1] == "string" && match[1].length) { + element.attribs[match[1]] = match[2]; + } else if (typeof match[3] == "string" && match[3].length) { + element.attribs[match[3].toString()] = match[4].toString(); + } else if (typeof match[5] == "string" && match[5].length) { + element.attribs[match[5]] = match[6]; + } else if (typeof match[7] == "string" && match[7].length) { + element.attribs[match[7]] = match[7]; + } + } + } + + //Extracts the base tag name from the data value of an element + Parser.prototype.parseTagName = function Parser$parseTagName (data) { + if (data == null || data == "") + return(""); + var match = Parser._reTagName.exec(data); + if (!match) + return(""); + return((match[1] ? "/" : "") + match[2]); + } + + //Parses through HTML text and returns an array of found elements + //I admit, this function is rather large but splitting up had an noticeable impact on speed + Parser.prototype.parseTags = function Parser$parseTags () { + var bufferEnd = this._buffer.length - 1; + while (Parser._reTags.test(this._buffer)) { + this._next = Parser._reTags.lastIndex - 1; + var tagSep = this._buffer.charAt(this._next); //The currently found tag marker + var rawData = this._buffer.substring(this._current, this._next); //The next chunk of data to parse + + //A new element to eventually be appended to the element list + var element = { + raw: rawData + , data: (this._parseState == ElementType.Text) ? rawData : rawData.replace(Parser._reTrim, "") + , type: this._parseState + }; + + var elementName = this.parseTagName(element.data); + + //This section inspects the current tag stack and modifies the current + //element if we're actually parsing a special area (script/comment/style tag) + if (this._tagStack.length) { //We're parsing inside a script/comment/style tag + if (this._tagStack[this._tagStack.length - 1] == ElementType.Script) { //We're currently in a script tag + if (elementName == "/script") //Actually, we're no longer in a script tag, so pop it off the stack + this._tagStack.pop(); + else { //Not a closing script tag + if (element.raw.indexOf("!--") != 0) { //Make sure we're not in a comment + //All data from here to script close is now a text element + element.type = ElementType.Text; + //If the previous element is text, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Text) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep + element.raw; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + } + } + } + } + else if (this._tagStack[this._tagStack.length - 1] == ElementType.Style) { //We're currently in a style tag + if (elementName == "/style") //Actually, we're no longer in a style tag, so pop it off the stack + this._tagStack.pop(); + else { + if (element.raw.indexOf("!--") != 0) { //Make sure we're not in a comment + //All data from here to style close is now a text element + element.type = ElementType.Text; + //If the previous element is text, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Text) { + if (element.raw != "") { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep + element.raw; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + } + else //Element is empty, so just append the last tag marker found + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep; + } + else //The previous element was not text + if (element.raw != "") + element.raw = element.data = element.raw; + } + } + } + else if (this._tagStack[this._tagStack.length - 1] == ElementType.Comment) { //We're currently in a comment tag + var rawLen = element.raw.length; + if (element.raw.charAt(rawLen - 2) == "-" && element.raw.charAt(rawLen - 1) == "-" && tagSep == ">") { + //Actually, we're no longer in a style tag, so pop it off the stack + this._tagStack.pop(); + //If the previous element is a comment, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Comment) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = (prevElement.raw + element.raw).replace(Parser._reTrimComment, ""); + element.raw = element.data = ""; //This causes the current element to not be added to the element list + element.type = ElementType.Text; + } + else //Previous element not a comment + element.type = ElementType.Comment; //Change the current element's type to a comment + } + else { //Still in a comment tag + element.type = ElementType.Comment; + //If the previous element is a comment, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Comment) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + element.raw + tagSep; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + element.type = ElementType.Text; + } + else + element.raw = element.data = element.raw + tagSep; + } + } + } + + //Processing of non-special tags + if (element.type == ElementType.Tag) { + element.name = elementName; + + if (element.raw.indexOf("!--") == 0) { //This tag is really comment + element.type = ElementType.Comment; + delete element["name"]; + var rawLen = element.raw.length; + //Check if the comment is terminated in the current element + if (element.raw.charAt(rawLen - 1) == "-" && element.raw.charAt(rawLen - 2) == "-" && tagSep == ">") + element.raw = element.data = element.raw.replace(Parser._reTrimComment, ""); + else { //It's not so push the comment onto the tag stack + element.raw += tagSep; + this._tagStack.push(ElementType.Comment); + } + } + else if (element.raw.indexOf("!") == 0 || element.raw.indexOf("?") == 0) { + element.type = ElementType.Directive; + //TODO: what about CDATA? + } + else if (element.name == "script") { + element.type = ElementType.Script; + //Special tag, push onto the tag stack if not terminated + if (element.data.charAt(element.data.length - 1) != "/") + this._tagStack.push(ElementType.Script); + } + else if (element.name == "/script") + element.type = ElementType.Script; + else if (element.name == "style") { + element.type = ElementType.Style; + //Special tag, push onto the tag stack if not terminated + if (element.data.charAt(element.data.length - 1) != "/") + this._tagStack.push(ElementType.Style); + } + else if (element.name == "/style") + element.type = ElementType.Style; + if (element.name && element.name.charAt(0) == "/") + element.data = element.name; + } + + //Add all tags and non-empty text elements to the element list + if (element.raw != "" || element.type != ElementType.Text) { + this.parseAttribs(element); + this._elements.push(element); + //If tag self-terminates, add an explicit, separate closing tag + if ( + element.type != ElementType.Text + && + element.type != ElementType.Comment + && + element.type != ElementType.Directive + && + element.data.charAt(element.data.length - 1) == "/" + ) + this._elements.push({ + raw: "/" + element.name + , data: "/" + element.name + , name: "/" + element.name + , type: element.type + }); + } + this._parseState = (tagSep == "<") ? ElementType.Tag : ElementType.Text; + this._current = this._next + 1; + this._prevTagSep = tagSep; + } + + this._buffer = (this._current <= bufferEnd) ? this._buffer.substring(this._current) : ""; + this._current = 0; + + this.writeHandler(); + } + + //Checks the handler to make it is an object with the right "interface" + Parser.prototype.validateHandler = function Parser$validateHandler (handler) { + if ((typeof handler) != "object") + throw new Error("Handler is not an object"); + if ((typeof handler.reset) != "function") + throw new Error("Handler method 'reset' is invalid"); + if ((typeof handler.done) != "function") + throw new Error("Handler method 'done' is invalid"); + if ((typeof handler.writeTag) != "function") + throw new Error("Handler method 'writeTag' is invalid"); + if ((typeof handler.writeText) != "function") + throw new Error("Handler method 'writeText' is invalid"); + if ((typeof handler.writeComment) != "function") + throw new Error("Handler method 'writeComment' is invalid"); + if ((typeof handler.writeDirective) != "function") + throw new Error("Handler method 'writeDirective' is invalid"); + } + + //Writes parsed elements out to the handler + Parser.prototype.writeHandler = function Parser$writeHandler (forceFlush) { + forceFlush = !!forceFlush; + if (this._tagStack.length && !forceFlush) + return; + while (this._elements.length) { + var element = this._elements.shift(); + switch (element.type) { + case ElementType.Comment: + this._handler.writeComment(element); + break; + case ElementType.Directive: + this._handler.writeDirective(element); + break; + case ElementType.Text: + this._handler.writeText(element); + break; + default: + this._handler.writeTag(element); + break; + } + } + } + + Parser.prototype.handleError = function Parser$handleError (error) { + if ((typeof this._handler.error) == "function") + this._handler.error(error); + else + throw error; + } + +//TODO: make this a trully streamable handler +function RssHandler (callback) { + RssHandler.super_.call(this, callback, { ignoreWhitespace: true, verbose: false, enforceEmptyTags: false }); +} +inherits(RssHandler, DefaultHandler); + + RssHandler.prototype.done = function RssHandler$done () { + var feed = { }; + var feedRoot; + + var found = DomUtils.getElementsByTagName(function (value) { return(value == "rss" || value == "feed"); }, this.dom, false); + if (found.length) { + feedRoot = found[0]; + } + if (feedRoot) { + if (feedRoot.name == "rss") { + feed.type = "rss"; + feedRoot = feedRoot.children[0]; // + feed.id = ""; +// require("sys").debug(require("sys").inspect(feedRoot, false, null)); +// require("sys").debug(require("sys").inspect(DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data, false, null)); + try { + feed.title = DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.link = DomUtils.getElementsByTagName("link", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.description = DomUtils.getElementsByTagName("description", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.updated = new Date(DomUtils.getElementsByTagName("lastBuildDate", feedRoot.children, false)[0].children[0].data); + } catch (ex) { } + try { + feed.author = DomUtils.getElementsByTagName("managingEditor", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + feed.items = []; + DomUtils.getElementsByTagName("item", feedRoot.children).forEach(function (item, index, list) { + var entry = {}; + try { + entry.id = DomUtils.getElementsByTagName("guid", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.title = DomUtils.getElementsByTagName("title", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.link = DomUtils.getElementsByTagName("link", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.description = DomUtils.getElementsByTagName("description", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.pubDate = new Date(DomUtils.getElementsByTagName("pubDate", item.children, false)[0].children[0].data); + } catch (ex) { } + feed.items.push(entry); + }); + } else { + feed.type = "atom"; + try { + feed.id = DomUtils.getElementsByTagName("id", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.title = DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.link = DomUtils.getElementsByTagName("link", feedRoot.children, false)[0].attribs.href; + } catch (ex) { } + try { + feed.description = DomUtils.getElementsByTagName("subtitle", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.updated = new Date(DomUtils.getElementsByTagName("updated", feedRoot.children, false)[0].children[0].data); + } catch (ex) { } + try { + feed.author = DomUtils.getElementsByTagName("email", feedRoot.children, true)[0].children[0].data; + } catch (ex) { } + feed.items = []; + DomUtils.getElementsByTagName("entry", feedRoot.children).forEach(function (item, index, list) { + var entry = {}; + try { + entry.id = DomUtils.getElementsByTagName("id", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.title = DomUtils.getElementsByTagName("title", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.link = DomUtils.getElementsByTagName("link", item.children, false)[0].attribs.href; + } catch (ex) { } + try { + entry.description = DomUtils.getElementsByTagName("summary", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.pubDate = new Date(DomUtils.getElementsByTagName("updated", item.children, false)[0].children[0].data); + } catch (ex) { } + feed.items.push(entry); + }); + } + + this.dom = feed; + } + RssHandler.super_.prototype.done.call(this); + } + +/////////////////////////////////////////////////// + +function DefaultHandler (callback, options) { + this.reset(); + this._options = options ? options : { }; + if (this._options.ignoreWhitespace == undefined) + this._options.ignoreWhitespace = false; //Keep whitespace-only text nodes + if (this._options.verbose == undefined) + this._options.verbose = true; //Keep data property for tags and raw property for all + if (this._options.enforceEmptyTags == undefined) + this._options.enforceEmptyTags = true; //Don't allow children for HTML tags defined as empty in spec + if ((typeof callback) == "function") + this._callback = callback; +} + + //**"Static"**// + //HTML Tags that shouldn't contain child nodes + DefaultHandler._emptyTags = { + area: 1 + , base: 1 + , basefont: 1 + , br: 1 + , col: 1 + , frame: 1 + , hr: 1 + , img: 1 + , input: 1 + , isindex: 1 + , link: 1 + , meta: 1 + , param: 1 + , embed: 1 + } + //Regex to detect whitespace only text nodes + DefaultHandler.reWhitespace = /^\s*$/; + + //**Public**// + //Properties// + DefaultHandler.prototype.dom = null; //The hierarchical object containing the parsed HTML + //Methods// + //Resets the handler back to starting state + DefaultHandler.prototype.reset = function DefaultHandler$reset() { + this.dom = []; + this._done = false; + this._tagStack = []; + this._tagStack.last = function DefaultHandler$_tagStack$last () { + return(this.length ? this[this.length - 1] : null); + } + } + //Signals the handler that parsing is done + DefaultHandler.prototype.done = function DefaultHandler$done () { + this._done = true; + this.handleCallback(null); + } + DefaultHandler.prototype.writeTag = function DefaultHandler$writeTag (element) { + this.handleElement(element); + } + DefaultHandler.prototype.writeText = function DefaultHandler$writeText (element) { + if (this._options.ignoreWhitespace) + if (DefaultHandler.reWhitespace.test(element.data)) + return; + this.handleElement(element); + } + DefaultHandler.prototype.writeComment = function DefaultHandler$writeComment (element) { + this.handleElement(element); + } + DefaultHandler.prototype.writeDirective = function DefaultHandler$writeDirective (element) { + this.handleElement(element); + } + DefaultHandler.prototype.error = function DefaultHandler$error (error) { + this.handleCallback(error); + } + + //**Private**// + //Properties// + DefaultHandler.prototype._options = null; //Handler options for how to behave + DefaultHandler.prototype._callback = null; //Callback to respond to when parsing done + DefaultHandler.prototype._done = false; //Flag indicating whether handler has been notified of parsing completed + DefaultHandler.prototype._tagStack = null; //List of parents to the currently element being processed + //Methods// + DefaultHandler.prototype.handleCallback = function DefaultHandler$handleCallback (error) { + if ((typeof this._callback) != "function") + if (error) + throw error; + else + return; + this._callback(error, this.dom); + } + DefaultHandler.prototype.handleElement = function DefaultHandler$handleElement (element) { + if (this._done) + this.handleCallback(new Error("Writing to the handler after done() called is not allowed without a reset()")); + if (!this._options.verbose) { +// element.raw = null; //FIXME: Not clean + //FIXME: Serious performance problem using delete + delete element.raw; + if (element.type == "tag" || element.type == "script" || element.type == "style") + delete element.data; + } + if (!this._tagStack.last()) { //There are no parent elements + //If the element can be a container, add it to the tag stack and the top level list + if (element.type != ElementType.Text && element.type != ElementType.Comment && element.type != ElementType.Directive) { + if (element.name.charAt(0) != "/") { //Ignore closing tags that obviously don't have an opening tag + this.dom.push(element); + if (!this._options.enforceEmptyTags || !DefaultHandler._emptyTags[element.name]) { //Don't add tags to the tag stack that can't have children + this._tagStack.push(element); + } + } + } + else //Otherwise just add to the top level list + this.dom.push(element); + } + else { //There are parent elements + //If the element can be a container, add it as a child of the element + //on top of the tag stack and then add it to the tag stack + if (element.type != ElementType.Text && element.type != ElementType.Comment && element.type != ElementType.Directive) { + if (element.name.charAt(0) == "/") { + //This is a closing tag, scan the tagStack to find the matching opening tag + //and pop the stack up to the opening tag's parent + var baseName = element.name.substring(1); + if (!this._options.enforceEmptyTags || !DefaultHandler._emptyTags[baseName]) { + var pos = this._tagStack.length - 1; + while (pos > -1 && this._tagStack[pos--].name != baseName) { } + if (pos > -1 || this._tagStack[0].name == baseName) + while (pos < this._tagStack.length - 1) + this._tagStack.pop(); + } + } + else { //This is not a closing tag + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(element); + if (!this._options.enforceEmptyTags || !DefaultHandler._emptyTags[element.name]) //Don't add tags to the tag stack that can't have children + this._tagStack.push(element); + } + } + else { //This is not a container element + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(element); + } + } + } + + var DomUtils = { + testElement: function DomUtils$testElement (options, element) { + if (!element) { + return(false); + } + + for (var key in options) { + if (key == "tag_name") { + if (element.type != "tag" && element.type != "script" && element.type != "style") { + return(false); + } + return(options["tag_name"](element.name)); + } else if (key == "tag_type") { + return(options["tag_type"](element.type)); + } else if (key == "tag_contains") { + if (element.type != "text" && element.type != "comment" && element.type != "directive") { + return(false); + } + return(options["tag_contains"](element.data)); + } else { + return(element.attribs && options[key](element.attribs[key])); + } + } + + return(true); + } + + , getElements: function DomUtils$getElements (options, currentElement, recurse) { + recurse = (recurse === undefined || recurse === null) || !!recurse; + + if (!currentElement) { + return([]); + } + + var found = []; + var elementList; + + function getTest (checkVal) { + return(((typeof options[key]) == "function") ? checkVal : function (value) { return(value == checkVal); }); + } + for (var key in options) { + options[key] = getTest(options[key]); + } + + if (DomUtils.testElement(options, currentElement)) { + found.push(currentElement); + } + + if (recurse && currentElement.children) + elementList = currentElement.children; + else if (currentElement instanceof Array) + elementList = currentElement; + else + return(found); + + for (var i = 0; i < elementList.length; i++) + found = found.concat(DomUtils.getElements(options, elementList[i], recurse)); + + return(found); + } + + , getElementById: function DomUtils$getElementById (id, currentElement, recurse) { + recurse = (recurse === undefined || recurse === null) || !!recurse; + var result = DomUtils.getElements({ id: id }, currentElement, recurse); + return(result.length ? result[0] : null); + } + + , getElementsByTagName: function DomUtils$getElementsByTagName (name, currentElement, recurse) { + recurse = (recurse === undefined || recurse === null) || !!recurse; + return(DomUtils.getElements({ tag_name: name }, currentElement, recurse)); + } + + , getElementsByTagType: function DomUtils$getElementsByTagType (type, currentElement, recurse) { + recurse = (recurse === undefined || recurse === null) || !!recurse; + return(DomUtils.getElements({ tag_type: type }, currentElement, recurse)); + } + } + + function inherits (ctor, superCtor) { + var tempCtor = function(){}; + tempCtor.prototype = superCtor.prototype; + ctor.super_ = superCtor; + ctor.prototype = new tempCtor(); + ctor.prototype.constructor = ctor; + } + +exports.Parser = Parser; + +exports.DefaultHandler = DefaultHandler; + +exports.RssHandler = RssHandler; + +exports.ElementType = ElementType; + +exports.DomUtils = DomUtils; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/package.json b/node_modules/jsdom/node_modules/htmlparser/package.json new file mode 100644 index 0000000..9e3a64a --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/package.json @@ -0,0 +1,44 @@ +{ + "name": "htmlparser", + "description": "Forgiving HTML/XML/RSS Parser in JS for *both* Node and Browsers", + "version": "1.7.6", + "author": { + "name": "Chris Winberry", + "email": "chris@winberry.net" + }, + "contributors": [], + "repository": { + "type": "git", + "url": "https://github.com/tautologistics/node-htmlparser" + }, + "keywords": [ + "html", + "xml", + "rss", + "parser" + ], + "directories": { + "lib": "./lib/" + }, + "main": "./lib/htmlparser", + "homepage": "http://github.com/tautologistics/node-htmlparser", + "bugs": { + "mail": "chris@winberry.net", + "url": "http://github.com/tautologistics/node-htmlparser/issues" + }, + "engines": { + "node": ">=0.1.33" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/tautologistics/node-htmlparser/raw/master/LICENSE" + } + ], + "readme": "#NodeHtmlParser\nA forgiving HTML/XML/RSS parser written in JS for both the browser and NodeJS (yes, despite the name it works just fine in any modern browser). The parser can handle streams (chunked data) and supports custom handlers for writing custom DOMs/output.\n\n##Installing\n\n\tnpm install htmlparser\n\n##Running Tests\n\n###Run tests under node:\n\tnode runtests.js\n\n###Run tests in browser:\nView runtests.html in any browser\n\n##Usage In Node\n\n```javascript\nvar htmlparser = require(\"htmlparser\");\nvar rawHtml = \"Xyz + , Style: "style" //Special tag + , Tag: "tag" //Any tag that isn't special + } + + function Parser (handler) { + this.validateHandler(handler); + this._handler = handler; + this.reset(); + } + + //**"Static"**// + //Regular expressions used for cleaning up and parsing (stateless) + Parser._reTrim = /(^\s+|\s+$)/g; //Trim leading/trailing whitespace + Parser._reTrimComment = /(^\!--|--$)/g; //Remove comment tag markup from comment contents + Parser._reWhitespace = /\s/g; //Used to find any whitespace to split on + Parser._reTagName = /^\s*(\/?)\s*([^\s\/]+)/; //Used to find the tag name for an element + + //Regular expressions used for parsing (stateful) + Parser._reAttrib = //Find attributes in a tag + /([^=<>\"\'\s]+)\s*=\s*"([^"]*)"|([^=<>\"\'\s]+)\s*=\s*'([^']*)'|([^=<>\"\'\s]+)\s*=\s*([^'"\s]+)|([^=<>\"\'\s\/]+)/g; +Parser._reTags = /[\<\>]/g; //Find tag markers + +//**Public**// +//Methods// +//Parses a complete HTML and pushes it to the handler +Parser.prototype.parseComplete = function Parser$parseComplete (data) { + this.reset(); + this.parseChunk(data); + this.done(); +} + +//Parses a piece of an HTML document +Parser.prototype.parseChunk = function Parser$parseChunk (data) { + if (this._done) + this.handleError(new Error("Attempted to parse chunk after parsing already done")); + this._buffer += data; //FIXME: this can be a bottleneck + this.parseTags(); +} + +//Tells the parser that the HTML being parsed is complete +Parser.prototype.done = function Parser$done () { + if (this._done) + return; + this._done = true; + + //Push any unparsed text into a final element in the element list + if (this._buffer.length) { + var rawData = this._buffer; + this._buffer = ""; + var element = { + raw: rawData + , data: (this._parseState == ElementType.Text) ? rawData : rawData.replace(Parser._reTrim, "") + , type: this._parseState + }; + if (this._parseState == ElementType.Tag || this._parseState == ElementType.Script || this._parseState == ElementType.Style) + element.name = this.parseTagName(element.data); + this.parseAttribs(element); + this._elements.push(element); + } + + this.writeHandler(); + this._handler.done(); +} + +//Resets the parser to a blank state, ready to parse a new HTML document +Parser.prototype.reset = function Parser$reset () { + this._buffer = ""; + this._done = false; + this._elements = []; + this._elementsCurrent = 0; + this._current = 0; + this._next = 0; + this._parseState = ElementType.Text; + this._prevTagSep = ''; + this._tagStack = []; + this._handler.reset(); +} + +//**Private**// +//Properties// +Parser.prototype._handler = null; //Handler for parsed elements +Parser.prototype._buffer = null; //Buffer of unparsed data +Parser.prototype._done = false; //Flag indicating whether parsing is done +Parser.prototype._elements = null; //Array of parsed elements +Parser.prototype._elementsCurrent = 0; //Pointer to last element in _elements that has been processed +Parser.prototype._current = 0; //Position in data that has already been parsed +Parser.prototype._next = 0; //Position in data of the next tag marker (<>) +Parser.prototype._parseState = ElementType.Text; //Current type of element being parsed +Parser.prototype._prevTagSep = ''; //Previous tag marker found +//Stack of element types previously encountered; keeps track of when +//parsing occurs inside a script/comment/style tag +Parser.prototype._tagStack = null; + +//Methods// +//Takes an array of elements and parses any found attributes +Parser.prototype.parseTagAttribs = function Parser$parseTagAttribs (elements) { + var idxEnd = elements.length; + var idx = 0; + + while (idx < idxEnd) { + var element = elements[idx++]; + if (element.type == ElementType.Tag || element.type == ElementType.Script || element.type == ElementType.style) + this.parseAttribs(element); + } + + return(elements); +} + +//Takes an element and adds an "attribs" property for any element attributes found +Parser.prototype.parseAttribs = function Parser$parseAttribs (element) { + //Only parse attributes for tags + if (element.type != ElementType.Script && element.type != ElementType.Style && element.type != ElementType.Tag) + return; + + var tagName = element.data.split(Parser._reWhitespace, 1)[0]; + var attribRaw = element.data.substring(tagName.length); + if (attribRaw.length < 1) + return; + + var match; + Parser._reAttrib.lastIndex = 0; + while (match = Parser._reAttrib.exec(attribRaw)) { + if (element.attribs == undefined) + element.attribs = {}; + + if (typeof match[1] == "string" && match[1].length) { + element.attribs[match[1]] = match[2]; + } else if (typeof match[3] == "string" && match[3].length) { + element.attribs[match[3].toString()] = match[4].toString(); + } else if (typeof match[5] == "string" && match[5].length) { + element.attribs[match[5]] = match[6]; + } else if (typeof match[7] == "string" && match[7].length) { + element.attribs[match[7]] = match[7]; + } + } +} + +//Extracts the base tag name from the data value of an element +Parser.prototype.parseTagName = function Parser$parseTagName (data) { + if (data == null || data == "") + return(""); + var match = Parser._reTagName.exec(data); + if (!match) + return(""); + return((match[1] ? "/" : "") + match[2]); +} + +//Parses through HTML text and returns an array of found elements +//I admit, this function is rather large but splitting up had an noticeable impact on speed +Parser.prototype.parseTags = function Parser$parseTags () { + var bufferEnd = this._buffer.length - 1; + while (Parser._reTags.test(this._buffer)) { + this._next = Parser._reTags.lastIndex - 1; + var tagSep = this._buffer.charAt(this._next); //The currently found tag marker + var rawData = this._buffer.substring(this._current, this._next); //The next chunk of data to parse + + //A new element to eventually be appended to the element list + var element = { + raw: rawData + , data: (this._parseState == ElementType.Text) ? rawData : rawData.replace(Parser._reTrim, "") + , type: this._parseState + }; + + var elementName = this.parseTagName(element.data); + + //This section inspects the current tag stack and modifies the current + //element if we're actually parsing a special area (script/comment/style tag) + if (this._tagStack.length) { //We're parsing inside a script/comment/style tag + if (this._tagStack[this._tagStack.length - 1] == ElementType.Script) { //We're currently in a script tag + if (elementName == "/script") //Actually, we're no longer in a script tag, so pop it off the stack + this._tagStack.pop(); + else { //Not a closing script tag + if (element.raw.indexOf("!--") != 0) { //Make sure we're not in a comment + //All data from here to script close is now a text element + element.type = ElementType.Text; + //If the previous element is text, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Text) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep + element.raw; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + } + } + } + } + else if (this._tagStack[this._tagStack.length - 1] == ElementType.Style) { //We're currently in a style tag + if (elementName == "/style") //Actually, we're no longer in a style tag, so pop it off the stack + this._tagStack.pop(); + else { + if (element.raw.indexOf("!--") != 0) { //Make sure we're not in a comment + //All data from here to style close is now a text element + element.type = ElementType.Text; + //If the previous element is text, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Text) { + if (element.raw != "") { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep + element.raw; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + } + else{ //Element is empty, so just append the last tag marker found + if (prevElement) { + prevElement.raw = prevElement.data = prevElement.raw + this._prevTagSep; + } + } + } + else //The previous element was not text + if (element.raw != "") + element.raw = element.data = element.raw; + } + } + } + else if (this._tagStack[this._tagStack.length - 1] == ElementType.Comment) { //We're currently in a comment tag + var rawLen = element.raw.length; + if (element.raw.charAt(rawLen - 2) == "-" && element.raw.charAt(rawLen - 1) == "-" && tagSep == ">") { + //Actually, we're no longer in a style tag, so pop it off the stack + this._tagStack.pop(); + //If the previous element is a comment, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Comment) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = (prevElement.raw + element.raw).replace(Parser._reTrimComment, ""); + element.raw = element.data = ""; //This causes the current element to not be added to the element list + element.type = ElementType.Text; + } + else //Previous element not a comment + element.type = ElementType.Comment; //Change the current element's type to a comment + } + else { //Still in a comment tag + element.type = ElementType.Comment; + //If the previous element is a comment, append the current text to it + if (this._elements.length && this._elements[this._elements.length - 1].type == ElementType.Comment) { + var prevElement = this._elements[this._elements.length - 1]; + prevElement.raw = prevElement.data = prevElement.raw + element.raw + tagSep; + element.raw = element.data = ""; //This causes the current element to not be added to the element list + element.type = ElementType.Text; + } + else + element.raw = element.data = element.raw + tagSep; + } + } + } + + //Processing of non-special tags + if (element.type == ElementType.Tag) { + element.name = elementName; + + if (element.raw.indexOf("!--") == 0) { //This tag is really comment + element.type = ElementType.Comment; + delete element["name"]; + var rawLen = element.raw.length; + //Check if the comment is terminated in the current element + if (element.raw.charAt(rawLen - 1) == "-" && element.raw.charAt(rawLen - 2) == "-" && tagSep == ">") + element.raw = element.data = element.raw.replace(Parser._reTrimComment, ""); + else { //It's not so push the comment onto the tag stack + element.raw += tagSep; + this._tagStack.push(ElementType.Comment); + } + } + else if (element.raw.indexOf("!") == 0 || element.raw.indexOf("?") == 0) { + element.type = ElementType.Directive; + //TODO: what about CDATA? + } + else if (element.name == "script") { + element.type = ElementType.Script; + //Special tag, push onto the tag stack if not terminated + if (element.data.charAt(element.data.length - 1) != "/") + this._tagStack.push(ElementType.Script); + } + else if (element.name == "/script") + element.type = ElementType.Script; + else if (element.name == "style") { + element.type = ElementType.Style; + //Special tag, push onto the tag stack if not terminated + if (element.data.charAt(element.data.length - 1) != "/") + this._tagStack.push(ElementType.Style); + } + else if (element.name == "/style") + element.type = ElementType.Style; + if (element.name && element.name.charAt(0) == "/") + element.data = element.name; + } + + //Add all tags and non-empty text elements to the element list + if (element.raw != "" || element.type != ElementType.Text) { + this.parseAttribs(element); + this._elements.push(element); + //If tag self-terminates, add an explicit, separate closing tag + if ( + element.type != ElementType.Text + && + element.type != ElementType.Comment + && + element.type != ElementType.Directive + && + element.data.charAt(element.data.length - 1) == "/" + ) + this._elements.push({ + raw: "/" + element.name + , data: "/" + element.name + , name: "/" + element.name + , type: element.type + }); + } + this._parseState = (tagSep == "<") ? ElementType.Tag : ElementType.Text; + this._current = this._next + 1; + this._prevTagSep = tagSep; + } + + this._buffer = (this._current <= bufferEnd) ? this._buffer.substring(this._current) : ""; + this._current = 0; + + this.writeHandler(); +} + +//Checks the handler to make it is an object with the right "interface" +Parser.prototype.validateHandler = function Parser$validateHandler (handler) { + if ((typeof handler) != "object") + throw new Error("Handler is not an object"); + if ((typeof handler.reset) != "function") + throw new Error("Handler method 'reset' is invalid"); + if ((typeof handler.done) != "function") + throw new Error("Handler method 'done' is invalid"); + if ((typeof handler.writeTag) != "function") + throw new Error("Handler method 'writeTag' is invalid"); + if ((typeof handler.writeText) != "function") + throw new Error("Handler method 'writeText' is invalid"); + if ((typeof handler.writeComment) != "function") + throw new Error("Handler method 'writeComment' is invalid"); + if ((typeof handler.writeDirective) != "function") + throw new Error("Handler method 'writeDirective' is invalid"); +} + +//Writes parsed elements out to the handler +Parser.prototype.writeHandler = function Parser$writeHandler (forceFlush) { + forceFlush = !!forceFlush; + if (this._tagStack.length && !forceFlush) + return; + while (this._elements.length) { + var element = this._elements.shift(); + switch (element.type) { + case ElementType.Comment: + this._handler.writeComment(element); + break; + case ElementType.Directive: + this._handler.writeDirective(element); + break; + case ElementType.Text: + this._handler.writeText(element); + break; + default: + this._handler.writeTag(element); + break; + } + } +} + +Parser.prototype.handleError = function Parser$handleError (error) { + if ((typeof this._handler.error) == "function") + this._handler.error(error); + else + throw error; +} + +//TODO: make this a trully streamable handler +function RssHandler (callback) { + RssHandler.super_.call(this, callback, { ignoreWhitespace: true, verbose: false, enforceEmptyTags: false }); +} +inherits(RssHandler, DefaultHandler); + +RssHandler.prototype.done = function RssHandler$done () { + var feed = { }; + var feedRoot; + + var found = DomUtils.getElementsByTagName(function (value) { return(value == "rss" || value == "feed"); }, this.dom, false); + if (found.length) { + feedRoot = found[0]; + } + if (feedRoot) { + if (feedRoot.name == "rss") { + feed.type = "rss"; + feedRoot = feedRoot.children[0]; // + feed.id = ""; + try { + feed.title = DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.link = DomUtils.getElementsByTagName("link", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.description = DomUtils.getElementsByTagName("description", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.updated = new Date(DomUtils.getElementsByTagName("lastBuildDate", feedRoot.children, false)[0].children[0].data); + } catch (ex) { } + try { + feed.author = DomUtils.getElementsByTagName("managingEditor", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + feed.items = []; + DomUtils.getElementsByTagName("item", feedRoot.children).forEach(function (item, index, list) { + var entry = {}; + try { + entry.id = DomUtils.getElementsByTagName("guid", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.title = DomUtils.getElementsByTagName("title", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.link = DomUtils.getElementsByTagName("link", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.description = DomUtils.getElementsByTagName("description", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.pubDate = new Date(DomUtils.getElementsByTagName("pubDate", item.children, false)[0].children[0].data); + } catch (ex) { } + feed.items.push(entry); + }); + } else { + feed.type = "atom"; + try { + feed.id = DomUtils.getElementsByTagName("id", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.title = DomUtils.getElementsByTagName("title", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.link = DomUtils.getElementsByTagName("link", feedRoot.children, false)[0].attribs.href; + } catch (ex) { } + try { + feed.description = DomUtils.getElementsByTagName("subtitle", feedRoot.children, false)[0].children[0].data; + } catch (ex) { } + try { + feed.updated = new Date(DomUtils.getElementsByTagName("updated", feedRoot.children, false)[0].children[0].data); + } catch (ex) { } + try { + feed.author = DomUtils.getElementsByTagName("email", feedRoot.children, true)[0].children[0].data; + } catch (ex) { } + feed.items = []; + DomUtils.getElementsByTagName("entry", feedRoot.children).forEach(function (item, index, list) { + var entry = {}; + try { + entry.id = DomUtils.getElementsByTagName("id", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.title = DomUtils.getElementsByTagName("title", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.link = DomUtils.getElementsByTagName("link", item.children, false)[0].attribs.href; + } catch (ex) { } + try { + entry.description = DomUtils.getElementsByTagName("summary", item.children, false)[0].children[0].data; + } catch (ex) { } + try { + entry.pubDate = new Date(DomUtils.getElementsByTagName("updated", item.children, false)[0].children[0].data); + } catch (ex) { } + feed.items.push(entry); + }); + } + + this.dom = feed; + } + RssHandler.super_.prototype.done.call(this); +} + +/////////////////////////////////////////////////// + +function DefaultHandler (callback, options) { + this.reset(); + this._options = options ? options : { }; + if (this._options.ignoreWhitespace == undefined) + this._options.ignoreWhitespace = false; //Keep whitespace-only text nodes + if (this._options.verbose == undefined) + this._options.verbose = true; //Keep data property for tags and raw property for all + if (this._options.enforceEmptyTags == undefined) + this._options.enforceEmptyTags = true; //Don't allow children for HTML tags defined as empty in spec + if ((typeof callback) == "function") + this._callback = callback; +} + +//**"Static"**// +//HTML Tags that shouldn't contain child nodes +DefaultHandler._emptyTags = { + area: 1 + , base: 1 + , basefont: 1 + , br: 1 + , col: 1 + , frame: 1 + , hr: 1 + , img: 1 + , input: 1 + , isindex: 1 + , link: 1 + , meta: 1 + , param: 1 + , embed: 1 +} +//Regex to detect whitespace only text nodes +DefaultHandler.reWhitespace = /^\s*$/; + +//**Public**// +//Properties// +DefaultHandler.prototype.dom = null; //The hierarchical object containing the parsed HTML +//Methods// +//Resets the handler back to starting state +DefaultHandler.prototype.reset = function DefaultHandler$reset() { + this.dom = []; + this._done = false; + this._tagStack = []; + this._tagStack.last = function DefaultHandler$_tagStack$last () { + return(this.length ? this[this.length - 1] : null); + } +} +//Signals the handler that parsing is done +DefaultHandler.prototype.done = function DefaultHandler$done () { + this._done = true; + this.handleCallback(null); +} +DefaultHandler.prototype.writeTag = function DefaultHandler$writeTag (element) { + this.handleElement(element); +} +DefaultHandler.prototype.writeText = function DefaultHandler$writeText (element) { + if (this._options.ignoreWhitespace) + if (DefaultHandler.reWhitespace.test(element.data)) + return; + this.handleElement(element); +} +DefaultHandler.prototype.writeComment = function DefaultHandler$writeComment (element) { + this.handleElement(element); +} +DefaultHandler.prototype.writeDirective = function DefaultHandler$writeDirective (element) { + this.handleElement(element); +} +DefaultHandler.prototype.error = function DefaultHandler$error (error) { + this.handleCallback(error); +} + +//**Private**// +//Properties// +DefaultHandler.prototype._options = null; //Handler options for how to behave +DefaultHandler.prototype._callback = null; //Callback to respond to when parsing done +DefaultHandler.prototype._done = false; //Flag indicating whether handler has been notified of parsing completed +DefaultHandler.prototype._tagStack = null; //List of parents to the currently element being processed +//Methods// +DefaultHandler.prototype.handleCallback = function DefaultHandler$handleCallback (error) { + if ((typeof this._callback) != "function") + if (error) + throw error; + else + return; + this._callback(error, this.dom); +} +DefaultHandler.prototype.handleElement = function DefaultHandler$handleElement (element) { + if (this._done) + this.handleCallback(new Error("Writing to the handler after done() called is not allowed without a reset()")); + if (!this._options.verbose) { + // element.raw = null; //FIXME: Not clean + //FIXME: Serious performance problem using delete + delete element.raw; + if (element.type == "tag" || element.type == "script" || element.type == "style") + delete element.data; + } + if (!this._tagStack.last()) { //There are no parent elements + //If the element can be a container, add it to the tag stack and the top level list + if (element.type != ElementType.Text && element.type != ElementType.Comment && element.type != ElementType.Directive) { + if (element.name.charAt(0) != "/") { //Ignore closing tags that obviously don't have an opening tag + this.dom.push(element); + if (!this._options.enforceEmptyTags || !DefaultHandler._emptyTags[element.name]) { //Don't add tags to the tag stack that can't have children + this._tagStack.push(element); + } + } + } + else //Otherwise just add to the top level list + this.dom.push(element); + } + else { //There are parent elements + //If the element can be a container, add it as a child of the element + //on top of the tag stack and then add it to the tag stack + if (element.type != ElementType.Text && element.type != ElementType.Comment && element.type != ElementType.Directive) { + if (element.name.charAt(0) == "/") { + //This is a closing tag, scan the tagStack to find the matching opening tag + //and pop the stack up to the opening tag's parent + var baseName = element.name.substring(1); + if (!this._options.enforceEmptyTags || !DefaultHandler._emptyTags[baseName]) { + var pos = this._tagStack.length - 1; + while (pos > -1 && this._tagStack[pos--].name != baseName) { } + if (pos > -1 || this._tagStack[0].name == baseName) + while (pos < this._tagStack.length - 1) + this._tagStack.pop(); + } + } + else { //This is not a closing tag + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(element); + if (!this._options.enforceEmptyTags || !DefaultHandler._emptyTags[element.name]) //Don't add tags to the tag stack that can't have children + this._tagStack.push(element); + } + } + else { //This is not a container element + if (!this._tagStack.last().children) + this._tagStack.last().children = []; + this._tagStack.last().children.push(element); + } + } +} + +var DomUtils = { + testElement: function DomUtils$testElement (options, element) { + if (!element) { + return false; + } + + for (var key in options) { + if (key == "tag_name") { + if (element.type != "tag" && element.type != "script" && element.type != "style") { + return false; + } + if (!options["tag_name"](element.name)) { + return false; + } + } else if (key == "tag_type") { + if (!options["tag_type"](element.type)) { + return false; + } + } else if (key == "tag_contains") { + if (element.type != "text" && element.type != "comment" && element.type != "directive") { + return false; + } + if (!options["tag_contains"](element.data)) { + return false; + } + } else { + if (!element.attribs || !options[key](element.attribs[key])) { + return false; + } + } + } + + return true; + } + + , getElements: function DomUtils$getElements (options, currentElement, recurse, limit) { + recurse = (recurse === undefined || recurse === null) || !!recurse; + limit = isNaN(parseInt(limit)) ? -1 : parseInt(limit); + + if (!currentElement) { + return([]); + } + + var found = []; + var elementList; + + function getTest (checkVal) { + return(function (value) { return(value == checkVal); }); + } + for (var key in options) { + if ((typeof options[key]) != "function") { + options[key] = getTest(options[key]); + } + } + + if (DomUtils.testElement(options, currentElement)) { + found.push(currentElement); + } + + if (limit >= 0 && found.length >= limit) { + return(found); + } + + if (recurse && currentElement.children) { + elementList = currentElement.children; + } else if (currentElement instanceof Array) { + elementList = currentElement; + } else { + return(found); + } + + for (var i = 0; i < elementList.length; i++) { + found = found.concat(DomUtils.getElements(options, elementList[i], recurse, limit)); + if (limit >= 0 && found.length >= limit) { + break; + } + } + + return(found); + } + + , getElementById: function DomUtils$getElementById (id, currentElement, recurse) { + var result = DomUtils.getElements({ id: id }, currentElement, recurse, 1); + return(result.length ? result[0] : null); + } + + , getElementsByTagName: function DomUtils$getElementsByTagName (name, currentElement, recurse, limit) { + return(DomUtils.getElements({ tag_name: name }, currentElement, recurse, limit)); + } + + , getElementsByTagType: function DomUtils$getElementsByTagType (type, currentElement, recurse, limit) { + return(DomUtils.getElements({ tag_type: type }, currentElement, recurse, limit)); + } +} + +function inherits (ctor, superCtor) { + var tempCtor = function(){}; + tempCtor.prototype = superCtor.prototype; + ctor.super_ = superCtor; + ctor.prototype = new tempCtor(); + ctor.prototype.constructor = ctor; +} + +exports.Parser = Parser; + +exports.DefaultHandler = DefaultHandler; + +exports.RssHandler = RssHandler; + +exports.ElementType = ElementType; + +exports.DomUtils = DomUtils; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/lib/node-htmlparser.min.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/lib/node-htmlparser.min.js new file mode 100644 index 0000000..5ab1e72 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/lib/node-htmlparser.min.js @@ -0,0 +1,22 @@ +/*********************************************** +Copyright 2010, Chris Winberry . All rights reserved. +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. +***********************************************/ +/* v1.6.3 */ +(function(){function e(a){this.validateHandler(a);this._handler=a;this.reset()}function n(a){n.super_.call(this,a,{ignoreWhitespace:true,verbose:false,enforceEmptyTags:false})}function g(a,c){this.reset();this._options=c?c:{};if(this._options.ignoreWhitespace==undefined)this._options.ignoreWhitespace=false;if(this._options.verbose==undefined)this._options.verbose=true;if(this._options.enforceEmptyTags==undefined)this._options.enforceEmptyTags=true;if(typeof a=="function")this._callback=a}if(!(typeof require== "function"&&typeof exports=="object"&&typeof module=="object"&&typeof __filename=="string"&&typeof __dirname=="string")){if(this.Tautologistics){if(this.Tautologistics.NodeHtmlParser)return}else this.Tautologistics={};this.Tautologistics.NodeHtmlParser={};exports=this.Tautologistics.NodeHtmlParser}var d={Text:"text",Directive:"directive",Comment:"comment",Script:"script",Style:"style",Tag:"tag"};e._reTrim=/(^\s+|\s+$)/g;e._reTrimComment=/(^\!--|--$)/g;e._reWhitespace=/\s/g;e._reTagName=/^\s*(\/?)\s*([^\s\/]+)/; e._reAttrib=/([^=<>\"\'\s]+)\s*=\s*"([^"]*)"|([^=<>\"\'\s]+)\s*=\s*'([^']*)'|([^=<>\"\'\s]+)\s*=\s*([^'"\s]+)|([^=<>\"\'\s\/]+)/g;e._reTags=/[\<\>]/g;e.prototype.parseComplete=function(a){this.reset();this.parseChunk(a);this.done()};e.prototype.parseChunk=function(a){this._done&&this.handleError(Error("Attempted to parse chunk after parsing already done"));this._buffer+=a;this.parseTags()};e.prototype.done=function(){if(!this._done){this._done=true;if(this._buffer.length){var a=this._buffer;this._buffer= "";a={raw:a,data:this._parseState==d.Text?a:a.replace(e._reTrim,""),type:this._parseState};if(this._parseState==d.Tag||this._parseState==d.Script||this._parseState==d.Style)a.name=this.parseTagName(a.data);this.parseAttribs(a);this._elements.push(a)}this.writeHandler();this._handler.done()}};e.prototype.reset=function(){this._buffer="";this._done=false;this._elements=[];this._next=this._current=this._elementsCurrent=0;this._parseState=d.Text;this._prevTagSep="";this._tagStack=[];this._handler.reset()}; e.prototype._handler=null;e.prototype._buffer=null;e.prototype._done=false;e.prototype._elements=null;e.prototype._elementsCurrent=0;e.prototype._current=0;e.prototype._next=0;e.prototype._parseState=d.Text;e.prototype._prevTagSep="";e.prototype._tagStack=null;e.prototype.parseTagAttribs=function(a){for(var c=a.length,b=0;b"){this._tagStack.pop();if(this._elements.length&&this._elements[this._elements.length-1].type==d.Comment){i=this._elements[this._elements.length-1];i.raw=i.data=(i.raw+b.raw).replace(e._reTrimComment, "");b.raw=b.data="";b.type=d.Text}else b.type=d.Comment}else{b.type=d.Comment;if(this._elements.length&&this._elements[this._elements.length-1].type==d.Comment){i=this._elements[this._elements.length-1];i.raw=i.data=i.raw+b.raw+c;b.raw=b.data="";b.type=d.Text}else b.raw=b.data=b.raw+c}}if(b.type==d.Tag){b.name=h;if(b.raw.indexOf("!--")==0){b.type=d.Comment;delete b.name;j=b.raw.length;if(b.raw.charAt(j-1)=="-"&&b.raw.charAt(j-2)=="-"&&c==">")b.raw=b.data=b.raw.replace(e._reTrimComment,"");else{b.raw+= c;this._tagStack.push(d.Comment)}}else if(b.raw.indexOf("!")==0||b.raw.indexOf("?")==0)b.type=d.Directive;else if(b.name=="script"){b.type=d.Script;b.data.charAt(b.data.length-1)!="/"&&this._tagStack.push(d.Script)}else if(b.name=="/script")b.type=d.Script;else if(b.name=="style"){b.type=d.Style;b.data.charAt(b.data.length-1)!="/"&&this._tagStack.push(d.Style)}else if(b.name=="/style")b.type=d.Style;if(b.name&&b.name.charAt(0)=="/")b.data=b.name}if(b.raw!=""||b.type!=d.Text){this.parseAttribs(b); this._elements.push(b);b.type!=d.Text&&b.type!=d.Comment&&b.type!=d.Directive&&b.data.charAt(b.data.length-1)=="/"&&this._elements.push({raw:"/"+b.name,data:"/"+b.name,name:"/"+b.name,type:b.type})}this._parseState=c=="<"?d.Tag:d.Text;this._current=this._next+1;this._prevTagSep=c}this._buffer=this._current<=a?this._buffer.substring(this._current):"";this._current=0;this.writeHandler()};e.prototype.validateHandler=function(a){if(typeof a!="object")throw Error("Handler is not an object");if(typeof a.reset!= "function")throw Error("Handler method 'reset' is invalid");if(typeof a.done!="function")throw Error("Handler method 'done' is invalid");if(typeof a.writeTag!="function")throw Error("Handler method 'writeTag' is invalid");if(typeof a.writeText!="function")throw Error("Handler method 'writeText' is invalid");if(typeof a.writeComment!="function")throw Error("Handler method 'writeComment' is invalid");if(typeof a.writeDirective!="function")throw Error("Handler method 'writeDirective' is invalid");}; e.prototype.writeHandler=function(a){a=!!a;if(!(this._tagStack.length&&!a))for(;this._elements.length;){a=this._elements.shift();switch(a.type){case d.Comment:this._handler.writeComment(a);break;case d.Directive:this._handler.writeDirective(a);break;case d.Text:this._handler.writeText(a);break;default:this._handler.writeTag(a)}}};e.prototype.handleError=function(a){if(typeof this._handler.error=="function")this._handler.error(a);else throw a;};(function(a,c){var b=function(){};b.prototype=c.prototype; a.super_=c;a.prototype=new b;a.prototype.constructor=a})(n,g);n.prototype.done=function(){var a={},c,b=f.getElementsByTagName(function(k){return k=="rss"||k=="feed"},this.dom,false);if(b.length)c=b[0];if(c){if(c.name=="rss"){a.type="rss";c=c.children[0];a.id="";try{a.title=f.getElementsByTagName("title",c.children,false)[0].children[0].data}catch(h){}try{a.link=f.getElementsByTagName("link",c.children,false)[0].children[0].data}catch(i){}try{a.description=f.getElementsByTagName("description",c.children, false)[0].children[0].data}catch(j){}try{a.updated=new Date(f.getElementsByTagName("lastBuildDate",c.children,false)[0].children[0].data)}catch(m){}try{a.author=f.getElementsByTagName("managingEditor",c.children,false)[0].children[0].data}catch(o){}a.items=[];f.getElementsByTagName("item",c.children).forEach(function(k){var l={};try{l.id=f.getElementsByTagName("guid",k.children,false)[0].children[0].data}catch(q){}try{l.title=f.getElementsByTagName("title",k.children,false)[0].children[0].data}catch(r){}try{l.link= f.getElementsByTagName("link",k.children,false)[0].children[0].data}catch(s){}try{l.description=f.getElementsByTagName("description",k.children,false)[0].children[0].data}catch(t){}try{l.pubDate=new Date(f.getElementsByTagName("pubDate",k.children,false)[0].children[0].data)}catch(u){}a.items.push(l)})}else{a.type="atom";try{a.id=f.getElementsByTagName("id",c.children,false)[0].children[0].data}catch(p){}try{a.title=f.getElementsByTagName("title",c.children,false)[0].children[0].data}catch(v){}try{a.link= f.getElementsByTagName("link",c.children,false)[0].attribs.href}catch(w){}try{a.description=f.getElementsByTagName("subtitle",c.children,false)[0].children[0].data}catch(x){}try{a.updated=new Date(f.getElementsByTagName("updated",c.children,false)[0].children[0].data)}catch(y){}try{a.author=f.getElementsByTagName("email",c.children,true)[0].children[0].data}catch(z){}a.items=[];f.getElementsByTagName("entry",c.children).forEach(function(k){var l={};try{l.id=f.getElementsByTagName("id",k.children, false)[0].children[0].data}catch(q){}try{l.title=f.getElementsByTagName("title",k.children,false)[0].children[0].data}catch(r){}try{l.link=f.getElementsByTagName("link",k.children,false)[0].attribs.href}catch(s){}try{l.description=f.getElementsByTagName("summary",k.children,false)[0].children[0].data}catch(t){}try{l.pubDate=new Date(f.getElementsByTagName("updated",k.children,false)[0].children[0].data)}catch(u){}a.items.push(l)})}this.dom=a}n.super_.prototype.done.call(this)};g._emptyTags={area:1, base:1,basefont:1,br:1,col:1,frame:1,hr:1,img:1,input:1,isindex:1,link:1,meta:1,param:1,embed:1};g.reWhitespace=/^\s*$/;g.prototype.dom=null;g.prototype.reset=function(){this.dom=[];this._done=false;this._tagStack=[];this._tagStack.last=function(){return this.length?this[this.length-1]:null}};g.prototype.done=function(){this._done=true;this.handleCallback(null)};g.prototype.writeTag=function(a){this.handleElement(a)};g.prototype.writeText=function(a){if(this._options.ignoreWhitespace)if(g.reWhitespace.test(a.data))return; this.handleElement(a)};g.prototype.writeComment=function(a){this.handleElement(a)};g.prototype.writeDirective=function(a){this.handleElement(a)};g.prototype.error=function(a){this.handleCallback(a)};g.prototype._options=null;g.prototype._callback=null;g.prototype._done=false;g.prototype._tagStack=null;g.prototype.handleCallback=function(a){if(typeof this._callback!="function")if(a)throw a;else return;this._callback(a,this.dom)};g.prototype.handleElement=function(a){this._done&&this.handleCallback(Error("Writing to the handler after done() called is not allowed without a reset()")); if(!this._options.verbose){delete a.raw;if(a.type=="tag"||a.type=="script"||a.type=="style")delete a.data}if(this._tagStack.last())if(a.type!=d.Text&&a.type!=d.Comment&&a.type!=d.Directive)if(a.name.charAt(0)=="/"){a=a.name.substring(1);if(!this._options.enforceEmptyTags||!g._emptyTags[a]){for(var c=this._tagStack.length-1;c>-1&&this._tagStack[c--].name!=a;);if(c>-1||this._tagStack[0].name==a)for(;c=0&&j.length>=h)return j;if(b&&c.children)c=c.children;else if(c instanceof Array)c=c;else return j;for(m=0;m=0&&j.length>=h)break}return j},getElementById:function(a,c,b){a=f.getElements({id:a},c,b,1);return a.length?a[0]:null},getElementsByTagName:function(a,c,b,h){return f.getElements({tag_name:a},c,b,h)},getElementsByTagType:function(a, c,b,h){return f.getElements({tag_type:a},c,b,h)}};exports.Parser=e;exports.DefaultHandler=g;exports.RssHandler=n;exports.ElementType=d;exports.DomUtils=f})(); \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/package.json b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/package.json new file mode 100644 index 0000000..ced4c0a --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/package.json @@ -0,0 +1,23 @@ +{ + "name": "htmlparser" + , "description": "Forgiving HTML/XML/RSS Parser in JS for *both* Node and Browsers" + , "version": "1.6.2" + , "author": "Chris Winberry " + , "contributors": [] + , "repository": { + "type": "git" + , "url": "git://github.com/tautologistics/node-htmlparser.git" + } + , "bugs": { + "mail": "chris@winberry.net" + , "web": "http://github.com/tautologistics/node-htmlparser/issues" + } + , "os": [ "linux", "darwin", "freebsd" ] + , "directories": { "lib": "./lib/" } + , "main": "./lib/node-htmlparser" + , "engines": { "node": ">=0.1.33" } + , "licenses": [{ + "type": "MIT" + , "url": "http://github.com/tautologistics/node-htmlparser/raw/master/LICENSE" + }] +} diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/profile.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/profile.js new file mode 100644 index 0000000..c5a474e --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/profile.js @@ -0,0 +1,63 @@ +//node --prof --prof_auto profile.js +//deps/v8/tools/mac-tick-processor v8.log +var sys = require("sys"); +var fs = require("fs"); +var http = require("http"); +var htmlparser = require("./node-htmlparser"); +var libxml = require('./libxmljs'); + +var testNHP = true; //Should node-htmlparser be exercised? +var testLXJS = true; //Should libxmljs be exercised? +var testIterations = 100; //Number of test loops to run + +var testHost = "nodejs.org"; //Host to fetch test HTML from +var testPort = 80; //Port on host to fetch test HTML from +var testPath = "/api.html"; //Path on host to fetch HTML from + +function getMillisecs () { + return((new Date()).getTime()); +} + +function timeExecutions (loops, func) { + var start = getMillisecs(); + + while (loops--) + func(); + + return(getMillisecs() - start); +} + +var html = ""; +http.createClient(testPort, testHost) + .request("GET", testPath, { host: testHost }) + .addListener("response", function (response) { + if (response.statusCode == "200") { + response.setEncoding("utf8"); + response.addListener("data", function (chunk) { + html += chunk; + }).addListener("end", function() { + var timeNodeHtmlParser = !testNHP ? 0 : timeExecutions(testIterations, function () { + var handler = new htmlparser.DefaultHandler(function(err, dom) { + if (err) + sys.debug("Error: " + err); + }); + var parser = new htmlparser.Parser(handler); + parser.parseComplete(html); + }) + + var timeLibXmlJs = !testLXJS ? 0 : timeExecutions(testIterations, function () { + var dom = libxml.parseHtmlString(html); + }) + + if (testNHP) + sys.debug("NodeHtmlParser: " + timeNodeHtmlParser); + if (testLXJS) + sys.debug("LibXmlJs: " + timeLibXmlJs); + if (testNHP && testLXJS) + sys.debug("Difference: " + ((timeNodeHtmlParser - timeLibXmlJs) / timeLibXmlJs) * 100); + }); + } + else + sys.debug("Error: got response status " + response.statusCode); + }) + .end(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.html b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.html new file mode 100644 index 0000000..3543adc --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.html @@ -0,0 +1,107 @@ + + + + + Node.js HTML Parser + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.js new file mode 100644 index 0000000..c59393c --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.js @@ -0,0 +1,75 @@ +/*********************************************** +Copyright 2010, Chris Winberry . All rights reserved. +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. +***********************************************/ + +var sys = require("sys"); +var fs = require("fs"); +var htmlparser = require("./lib/node-htmlparser"); + +var testFolder = "./tests"; +var chunkSize = 5; + +var testFiles = fs.readdirSync(testFolder); +var testCount = 0; +var failedCount = 0; +for (var i in testFiles) { + testCount++; + var fileParts = testFiles[i].split("."); + fileParts.pop(); + var moduleName = fileParts.join("."); + var test = require(testFolder + "/" + moduleName); + var handlerCallback = function handlerCallback (error) { + if (error) + sys.puts("Handler error: " + error); + } + var handler = (test.type == "rss") ? + new htmlparser.RssHandler(handlerCallback, test.options) + : + new htmlparser.DefaultHandler(handlerCallback, test.options) + ; + var parser = new htmlparser.Parser(handler); + parser.parseComplete(test.html); + var resultComplete = handler.dom; + var chunkPos = 0; + parser.reset(); + while (chunkPos < test.html.length) { + parser.parseChunk(test.html.substring(chunkPos, chunkPos + chunkSize)); + chunkPos += chunkSize; + } + parser.done(); + var resultChunk = handler.dom; + var testResult = + sys.inspect(resultComplete, false, null) === sys.inspect(test.expected, false, null) + && + sys.inspect(resultChunk, false, null) === sys.inspect(test.expected, false, null) + ; + sys.puts("[" + test.name + "\]: " + (testResult ? "passed" : "FAILED")); + if (!testResult) { + failedCount++; + sys.puts("== Complete =="); + sys.puts(sys.inspect(resultComplete, false, null)); + sys.puts("== Chunked =="); + sys.puts(sys.inspect(resultChunk, false, null)); + sys.puts("== Expected =="); + sys.puts(sys.inspect(test.expected, false, null)); + } +} +sys.puts("Total tests: " + testCount); +sys.puts("Failed tests: " + failedCount); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.min.html b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.min.html new file mode 100644 index 0000000..2ec9e8f --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.min.html @@ -0,0 +1,107 @@ + + + + + Node.js HTML Parser + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.min.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.min.js new file mode 100644 index 0000000..d32c3aa --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/runtests.min.js @@ -0,0 +1,75 @@ +/*********************************************** +Copyright 2010, Chris Winberry . All rights reserved. +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. +***********************************************/ + +var sys = require("sys"); +var fs = require("fs"); +var htmlparser = require("./lib/node-htmlparser.min"); + +var testFolder = "./tests"; +var chunkSize = 5; + +var testFiles = fs.readdirSync(testFolder); +var testCount = 0; +var failedCount = 0; +for (var i in testFiles) { + testCount++; + var fileParts = testFiles[i].split("."); + fileParts.pop(); + var moduleName = fileParts.join("."); + var test = require(testFolder + "/" + moduleName); + var handlerCallback = function handlerCallback (error) { + if (error) + sys.puts("Handler error: " + error); + } + var handler = (test.type == "rss") ? + new htmlparser.RssHandler(handlerCallback, test.options) + : + new htmlparser.DefaultHandler(handlerCallback, test.options) + ; + var parser = new htmlparser.Parser(handler); + parser.parseComplete(test.html); + var resultComplete = handler.dom; + var chunkPos = 0; + parser.reset(); + while (chunkPos < test.html.length) { + parser.parseChunk(test.html.substring(chunkPos, chunkPos + chunkSize)); + chunkPos += chunkSize; + } + parser.done(); + var resultChunk = handler.dom; + var testResult = + sys.inspect(resultComplete, false, null) === sys.inspect(test.expected, false, null) + && + sys.inspect(resultChunk, false, null) === sys.inspect(test.expected, false, null) + ; + sys.puts("[" + test.name + "\]: " + (testResult ? "passed" : "FAILED")); + if (!testResult) { + failedCount++; + sys.puts("== Complete =="); + sys.puts(sys.inspect(resultComplete, false, null)); + sys.puts("== Chunked =="); + sys.puts(sys.inspect(resultChunk, false, null)); + sys.puts("== Expected =="); + sys.puts(sys.inspect(test.expected, false, null)); + } +} +sys.puts("Total tests: " + testCount); +sys.puts("Failed tests: " + failedCount); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/snippet.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/snippet.js new file mode 100644 index 0000000..2f54b36 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/snippet.js @@ -0,0 +1,15 @@ +//node --prof --prof_auto profile.js +//deps/v8/tools/mac-tick-processor v8.log +var sys = require("sys"); +var htmlparser = require("./node-htmlparser"); + +var html = "text"; + +var handler = new htmlparser.DefaultHandler(function(err, dom) { + if (err) + sys.debug("Error: " + err); + else + sys.debug(sys.inspect(dom, false, null)); +}, { enforceEmptyTags: true }); +var parser = new htmlparser.Parser(handler); +parser.parseComplete(html); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/01-basic.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/01-basic.js new file mode 100644 index 0000000..57de7dc --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/01-basic.js @@ -0,0 +1,57 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Basic test"; +exports.html = "The TitleHello world"; +exports.expected = + [ { raw: 'html' + , data: 'html' + , type: 'tag' + , name: 'html' + , children: + [ { raw: 'title' + , data: 'title' + , type: 'tag' + , name: 'title' + , children: [ { raw: 'The Title', data: 'The Title', type: 'text' } ] + } + , { raw: 'body' + , data: 'body' + , type: 'tag' + , name: 'body' + , children: + [ { raw: 'Hello world' + , data: 'Hello world' + , type: 'text' + } + ] + } + ] + } + ]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/02-single_tag_1.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/02-single_tag_1.js new file mode 100644 index 0000000..8af04d9 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/02-single_tag_1.js @@ -0,0 +1,35 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Single Tag 1"; +exports.html = "
    text
    "; +exports.expected = + [ { raw: 'br', data: 'br', type: 'tag', name: 'br' } + , { raw: 'text', data: 'text', type: 'text' } + ]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/03-single_tag_2.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/03-single_tag_2.js new file mode 100644 index 0000000..beae642 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/03-single_tag_2.js @@ -0,0 +1,36 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Single Tag 2"; +exports.html = "
    text
    "; +exports.expected = + [ { raw: 'br', data: 'br', type: 'tag', name: 'br' } + , { raw: 'text', data: 'text', type: 'text' } + , { raw: 'br', data: 'br', type: 'tag', name: 'br' } + ]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/04-unescaped_in_script.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/04-unescaped_in_script.js new file mode 100644 index 0000000..1a23385 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/04-unescaped_in_script.js @@ -0,0 +1,52 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Unescaped chars in script"; +exports.html = ""; +exports.expected = +[ { raw: 'head' + , data: 'head' + , type: 'tag' + , name: 'head' + , children: + [ { raw: 'script language="Javascript"' + , data: 'script language="Javascript"' + , type: 'script' + , name: 'script' + , attribs: { language: 'Javascript' } + , children: + [ { raw: 'var foo = ""; alert(2 > foo); var baz = 10 << 2; var zip = 10 >> 1; var yap = \"<<>>>><<\";' + , data: 'var foo = ""; alert(2 > foo); var baz = 10 << 2; var zip = 10 >> 1; var yap = \"<<>>>><<\";' + , type: 'text' + } + ] + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/05-tags_in_comment.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/05-tags_in_comment.js new file mode 100644 index 0000000..79fdd8c --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/05-tags_in_comment.js @@ -0,0 +1,44 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Special char in comment"; +exports.html = ""; +exports.expected = +[ { raw: 'head' + , data: 'head' + , type: 'tag' + , name: 'head' + , children: + [ { raw: ' commented out tags Test' + , data: ' commented out tags Test' + , type: 'comment' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/06-comment_in_script.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/06-comment_in_script.js new file mode 100644 index 0000000..7737f38 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/06-comment_in_script.js @@ -0,0 +1,44 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Script source in comment"; +exports.html = ""; +exports.expected = +[ { raw: 'script' + , data: 'script' + , type: 'script' + , name: 'script' + , children: + [ { raw: 'var foo = 1;' + , data: 'var foo = 1;' + , type: 'comment' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/07-unescaped_in_style.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/07-unescaped_in_style.js new file mode 100644 index 0000000..fe4efad --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/07-unescaped_in_style.js @@ -0,0 +1,45 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Unescaped chars in style"; +exports.html = ""; +exports.expected = +[ { raw: 'style type="text/css"' + , data: 'style type="text/css"' + , type: 'style' + , name: 'style' + , attribs: { type: 'text/css' } + , children: + [ { raw: '\n body > p\n { font-weight: bold; }' + , data: '\n body > p\n { font-weight: bold; }' + , type: 'text' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/08-extra_spaces_in_tag.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/08-extra_spaces_in_tag.js new file mode 100644 index 0000000..84192af --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/08-extra_spaces_in_tag.js @@ -0,0 +1,45 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Extra spaces in tag"; +exports.html = "<\n font \n size='14' \n>the text<\n / \nfont \n>"; +exports.expected = +[ { raw: '\n font \n size=\'14\' \n' + , data: 'font \n size=\'14\'' + , type: 'tag' + , name: 'font' + , attribs: { size: '14' } + , children: + [ { raw: 'the text' + , data: 'the text' + , type: 'text' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/09-unquoted_attrib.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/09-unquoted_attrib.js new file mode 100644 index 0000000..3ad54e6 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/09-unquoted_attrib.js @@ -0,0 +1,45 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Unquoted attributes"; +exports.html = "the text"; +exports.expected = +[ { raw: 'font size= 14' + , data: 'font size= 14' + , type: 'tag' + , name: 'font' + , attribs: { size: '14' } + , children: + [ { raw: 'the text' + , data: 'the text' + , type: 'text' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/10-singular_attribute.js b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/10-singular_attribute.js new file mode 100644 index 0000000..37897dc --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/pulls/node-htmlparser/tests/10-singular_attribute.js @@ -0,0 +1,39 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Singular attribute"; +exports.html = "
    + + + + + + diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker.html.76922~ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker.html.76922~ new file mode 100644 index 0000000..b499243 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker.html.76922~ @@ -0,0 +1,10 @@ + + + + +Insert title here + + + + + \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker.html.80022~ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker.html.80022~ new file mode 100644 index 0000000..e000284 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker.html.80022~ @@ -0,0 +1,2948 @@ + + + +www.trackerchecker.com - We check your trackers + + + + + + +
    + + + + + + + +
    Home || Add a tracker || Latest trackers
    +
    + + +
    +follow us on Twitter
    +Follow trackerchecker on Twitter --> @trackerchecker. +
    + +
    + + +
    +
    + TrackerList
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     TrackerNameHistoryLastCheckedStatus
    1337x.orgview history2010-03-29 03:56:03Open
    420project.orgview history2010-03-29 04:28:13Closed
    acehd.netview history2010-03-29 04:31:58Closed
    acetorrents.netview history2010-03-29 03:59:08Open
    adult-cinema-network.netview history2010-03-29 04:00:08Open
    all4nothin.netview history2010-03-29 04:01:08Open
    allgirltorrents.comview history2010-03-29 03:50:57Closed
    allotracker.comview history2010-03-29 03:58:09Open
    appz.bitshock.orgview history2010-03-29 03:57:12Open
    appzuniverse.orgview history2010-03-29 04:18:04Closed
    arabfilms.orgview history2010-03-29 04:08:50Closed
    arabseries.orgview history2010-03-29 03:59:39Closed
    araditracker.comview history2010-03-29 04:22:25Closed
    arena-tr.comview history2010-03-29 04:12:10Closed
    arenabg.comview history2010-03-29 03:51:00Closed
    artofmisdirection.comview history2010-03-29 04:01:04Closed
    asiandvdclub.orgview history2010-03-29 04:18:15Open
    at-tracker.orgview history2010-03-29 04:15:08Offline
    atomico-torrent.comview history2010-03-29 03:56:05Closed
    audionews.ruview history2010-03-29 04:01:02Closed
    audiotracer.comview history2010-03-29 04:05:08Closed
    audiozonetorrents.comview history2010-03-29 03:56:09Open
    avatarbg.infoview history2010-03-29 03:49:14Closed
    awesome-hd.comview history2010-03-29 03:51:07Closed
    awesome-hd.netview history2010-03-29 03:55:09Closed
    baltracker.netview history2010-03-29 04:15:09Open
    bestmmatorrents.comview history2010-03-29 04:15:04Closed
    bestshare.roview history2010-03-29 03:56:11Closed
    bestxvid.orgview history2010-03-29 03:50:57Closed
    bit-hdtv.comview history2010-03-29 03:58:10Closed
    bitaddict.orgview history2010-03-29 03:50:45Closed
    bitchil.comview history2010-03-29 03:56:09Open
    bitflamers.comview history2010-03-29 04:01:12Closed
    bitgamer.comview history2010-03-29 04:12:08Closed
    bithq.orgview history2010-03-29 03:58:08Open
    bithumen.ath.cxview history2010-03-29 04:22:20Closed
    bitlove.huview history2010-03-29 04:25:10Closed
    bitme.orgview history2010-03-29 04:12:06Closed
    bitmetv.orgview history2010-03-29 03:49:16Closed
    bitmusic.huview history2010-03-29 03:58:11Closed
    bitnation.comview history2010-03-29 03:59:08Closed
    bitseduce.comview history2010-03-29 04:05:08Closed
    bitseek.orgview history2010-03-29 04:28:05Closed
    bitseek.orgview history2010-03-29 04:18:05Closed
    bitshock.orgview history2010-03-29 04:00:03Open
    bitshock.orgview history2010-03-29 03:55:14Closed
    bitsoup.orgview history2010-03-29 03:59:07Open
    bitSpyder.netview history2010-03-29 03:56:06Closed
    bittorrents.roview history2010-03-29 04:00:14Closed
    bitturk.netview history2010-03-29 03:56:05Closed
    biztorrents.comview history2010-03-29 04:15:07Open
    blackcats-games.netview history2010-03-29 03:58:06Closed
    blades-heaven.comview history2010-03-29 04:08:56Open
    blue-bytez.comview history2010-03-29 04:32:01Closed
    blue-whitegt.comview history2010-03-29 04:28:13Closed
    bmtorrents.netview history2010-03-29 03:58:10Closed
    bootytape.comview history2010-03-29 03:58:02Open
    bootytorrents.comview history2010-03-29 03:57:07Closed
    boxtorrents.comview history2010-03-29 04:08:59Closed
    bt.avistaz.comview history2010-03-29 04:15:08Closed
    bt.davka.infoview history2010-03-29 04:08:50Open
    bt.xbox-sky.ccview history2010-03-29 03:49:08Closed
    bt.xbox-sky.comview history2010-03-29 03:50:42Closed
    btgigs.infoview history2010-03-29 04:18:15Closed
    bwtorrents.comview history2010-03-29 03:56:10Closed
    bytelist.orgview history2010-03-29 04:05:07Offline
    cartoonchaos.orgview history2010-03-29 04:18:15Closed
    ccfbits.orgview history2010-03-29 04:22:19Closed
    chdbits.orgview history2010-03-29 04:15:11Closed
    cheggit.net/view history2010-03-29 04:09:00Open
    chilebt.comview history2010-03-29 04:22:11Closed
    christiantorrents.comview history2010-03-29 04:28:13Closed
    chronictracker.comview history2010-03-29 04:01:13Closed
    cinema-obscura.comview history2010-03-29 03:57:06Closed
    cinemageddon.orgview history2010-03-29 04:22:27Closed
    cinematik.netview history2010-03-29 03:57:11Closed
    cleanvobs.orgview history2010-03-29 03:49:43Closed
    colombo-bt.orgview history2010-03-29 03:50:55Closed
    contego.wsview history2010-03-29 04:22:12Closed
    crazytorrent.euview history2010-03-29 04:08:49Closed
    czone.roview history2010-03-29 04:24:09Closed
    danger.lvview history2010-03-29 03:55:15Closed
    demonoid.comview history2010-03-29 04:18:15Closed
    devilwolfs.comview history2010-03-29 04:31:55Closed
    diablotorrent.huview history2010-03-29 03:56:01Closed
    dididave.comview history2010-03-29 04:00:03Closed
    digitalhive.orgview history2010-03-29 03:50:44Closed
    dimeadozen.orgview history2010-03-29 04:05:06Open
    dnbtracker.orgview history2010-03-29 04:01:11Open
    docs.torrents.roview history2010-03-29 04:01:14Closed
    dvdseed.orgview history2010-03-29 04:32:01Closed
    dvdtreasure.euview history2010-03-29 04:05:04Closed
    ebookvortex.comview history2010-03-29 04:05:07Open
    eclipsetorrents.orgview history2010-03-29 04:12:09Closed
    egytorrent.comview history2010-03-29 03:49:06Closed
    egytorrent.comview history2010-03-29 04:01:05Closed
    elbitz.netview history2010-03-29 04:18:13Closed
    elektronik.roview history2010-03-29 03:55:02Closed
    empornium.usview history2010-03-29 03:57:07Open
    eroticsource.plview history2010-03-29 04:28:19Closed
    estrenoslatinos.comview history2010-03-29 03:49:10Closed
    ethor.netview history2010-03-29 03:51:08Closed
    evopt.orgview history2010-03-29 04:15:06Closed
    Exigomusicview history2010-03-29 03:50:45Closed
    extremebits.orgview history2010-03-29 04:28:05Closed
    extremeshare.orgview history2010-03-29 03:59:03Open
    faplife.netview history2010-03-29 03:50:46Closed
    feedthe.netview history2010-03-29 04:22:09Closed
    filebits.orgview history2010-03-29 03:57:08Closed
    filelist.orgview history2010-03-29 04:22:25Closed
    filelist.roview history2010-03-29 03:56:09Closed
    filemp3.orgview history2010-03-29 03:50:46Closed
    fileporn.orgview history2010-03-29 03:51:10Closed
    flashtorrents.com.arview history2010-03-29 03:59:40Closed
    Free The Scene (FTS)view history2010-03-29 04:05:04Closed
    Fresh On TV (TvT)view history2010-03-29 03:59:37Open
    frztracker.sytes.netview history2010-03-29 04:25:08Closed
    fst.omnilounge.co.ukview history2010-03-29 04:08:50Closed
    fullcontactzone.comview history2010-03-29 03:56:09Closed
    gamecrook.comview history2010-03-29 04:18:05Closed
    gbvnet.roview history2010-03-29 04:25:08Open
    gettorrents.orgview history2010-03-29 04:11:06Closed
    gfxnews.ruview history2010-03-29 04:12:07Closed
    gigatorrents.wsview history2010-03-29 03:57:05Closed
    globus-tracker.comview history2010-03-29 04:30:51Closed
    goem.orgview history2010-03-29 03:56:07Closed
    gormogon.comview history2010-03-29 04:25:05Open
    greek-tracker.comview history2010-03-29 03:51:06Closed
    grimetorrent.comview history2010-03-29 04:28:15Closed
    grtorrent.comview history2010-03-29 04:12:08Closed
    guiks.netview history2010-03-29 04:05:04Closed
    h264torrents.comview history2010-03-29 03:57:01Closed
    h33t.comview history2010-03-29 03:51:06Open
    hd-bits.roview history2010-03-29 04:18:09Closed
    hd-torrents.orgview history2010-03-29 04:05:05Closed
    hdbits.orgview history2010-03-29 04:12:07Closed
    hdchina.orgview history2010-03-29 03:59:37Closed
    hdfrench.comview history2010-03-29 04:09:01Closed
    hdme.euview history2010-03-29 03:55:09Open
    hdpre.comview history2010-03-29 04:12:09Closed
    hdsource.bizview history2010-03-29 03:49:13Closed
    hdstar.orgview history2010-03-29 03:51:02Closed
    hdvnbits.orgview history2010-03-29 03:56:03Closed
    heaventracker.orgview history2010-03-29 03:57:02Closed
    hermeticos.orgview history2010-03-29 04:25:12Closed
    horrorcharnel.kicks-ass.orgview history2010-03-29 03:58:05Closed
    hungercity.orgview history2010-03-29 04:31:05Open
    ifyounotknow.comview history2010-03-29 03:58:07Closed
    ilovetorrents.comview history2010-03-29 03:56:06Open
    indeep.bizview history2010-03-29 03:56:08Closed
    indietorrents.comview history2010-03-29 04:00:14Closed
    iplay.roview history2010-03-29 03:59:03Closed
    ipodnova.tvview history2010-03-29 04:04:12Closed
    iptorrents.comview history2010-03-29 03:51:06Closed
    joompalace.comview history2010-03-29 03:57:04Closed
    karagarga.netview history2010-03-29 04:17:07Closed
    killawaves.netview history2010-03-29 04:05:05Closed
    kinozal.wsview history2010-03-29 04:28:16Open
    kludd.comview history2010-03-29 03:55:11Closed
    lasttorrents.orgview history2010-03-29 04:32:02Open
    leecherslair.comview history2010-03-29 04:18:08Closed
    libble.comview history2010-03-29 04:25:11Closed
    libitina.netview history2010-03-29 04:18:11Closed
    linuxmafia.netview history2010-03-29 04:22:07Offline
    linuxtracker.orgview history2010-03-29 04:22:24Closed
    lostfilm.tvview history2010-03-29 04:00:07Open
    magiciantorrents.comview history2010-03-29 03:55:14Closed
    masterstb.comview history2010-03-29 03:56:12Closed
    mazetorrents.netview history2010-03-29 04:17:07Offline
    medioteka.comview history2010-03-29 04:17:07Closed
    mega-bits.comview history2010-03-29 03:51:52Closed
    mentol.roview history2010-03-29 04:12:04Closed
    metal.iplay.roview history2010-03-29 04:18:03Closed
    metalbits.orgview history2010-03-29 04:00:02Closed
    midnight-scene.comview history2010-03-29 03:58:06Closed
    midnight-torrents.comview history2010-03-29 04:31:05Closed
    mma-central.org.ukview history2010-03-29 03:56:05Closed
    mma-tracker.netview history2010-03-29 03:50:43Closed
    mp3nerds.orgview history2010-03-29 04:18:07Closed
    mucis-vid.comview history2010-03-29 03:56:06Closed
    musicplace.lvview history2010-03-29 04:05:04Closed
    mytorrent.tvview history2010-03-29 03:57:07Closed
    norbits.netview history2010-03-29 04:12:05Closed
    nordic-t.orgview history2010-03-29 03:55:02Closed
    nordicbits.orgview history2010-03-29 04:18:07Offline
    novaro.infoview history2010-03-29 03:49:16Closed
    novaro.infoview history2010-03-29 03:55:02Closed
    noviteti.comview history2010-03-29 04:15:05Offline
    ntorrents.netview history2010-03-29 03:59:08Closed
    nutorrent.comview history2010-03-29 04:25:12Open
    opennetwork.roview history2010-03-29 04:08:49Closed
    overtopropetorrents.comview history2010-03-29 04:00:14Closed
    ozone-torrents.orgview history2010-03-29 04:32:00Closed
    Pedros btmusicview history2010-03-29 04:08:54Closed
    pianosheets.orgview history2010-03-29 03:49:17Closed
    pinkytorrents.comview history2010-03-29 03:56:08Open
    piranha.excom.usview history2010-03-29 04:08:07Open
    Pirate The Net (PtN)view history2010-03-29 03:49:15Closed
    piratebits.orgview history2010-03-29 04:09:01Closed
    piratefiles.seview history2010-03-29 04:25:05Closed
    piratetorrents.nuview history2010-03-29 03:56:04Closed
    pisexy.orgview history2010-03-29 04:01:06Closed
    polishbytes.netview history2010-03-29 04:31:55Open
    polishtracker.orgview history2010-03-29 03:56:09Closed
    pornbay.orgview history2010-03-29 03:57:12Closed
    PotUKview history2010-03-29 04:08:54Closed
    powerscene.orgview history2010-03-29 03:57:11Closed
    pretome.netview history2010-03-29 04:32:01Closed
    proaudiotorrents.orgview history2010-03-29 04:15:14Closed
    psytorrents.infoview history2010-03-29 03:49:08Closed
    ptfiles.orgview history2010-03-29 04:18:09Closed
    punkhc.dyndns.orgview history2010-03-29 04:01:09Closed
    puretna.comview history2010-03-29 04:05:06Open
    pussytorrents.orgview history2010-03-29 03:52:02Open
    rapthe.netview history2010-03-29 04:12:09Closed
    rarbg.comview history2010-03-29 03:58:11Open
    reload-paradise.netview history2010-03-29 04:00:07Closed
    revolutiontt.netview history2010-03-29 03:56:07Closed
    rmvbustersview history2010-03-29 04:15:08Open
    rmvbusters.plview history2010-03-29 03:56:05Open
    scaliwags.orgview history2010-03-29 03:59:04Closed
    scene-gold.infoview history2010-03-29 04:17:08Offline
    scene-inspired.comview history2010-03-29 03:51:07Open
    sceneaccess.orgview history2010-03-29 03:55:09Closed
    scenebytes.clview history2010-03-29 04:22:20Closed
    scenehd.orgview history2010-03-29 04:28:09Closed
    sceneleech.orgview history2010-03-29 03:57:05Closed
    SceneLife (ScL)view history2010-03-29 04:00:08Closed
    scenetorrents.orgview history2010-03-29 04:12:05Closed
    scenetuga.orgview history2010-03-29 03:51:04Closed
    sciencehd.netview history2010-03-29 04:00:15Closed
    scifitorrents.netview history2010-03-29 03:56:10Closed
    secret-cinema.netview history2010-03-29 04:28:13Closed
    seedgames.orgview history2010-03-29 04:18:16Closed
    seedmore.orgview history2010-03-29 03:56:11Closed
    sharetorrents.plview history2010-03-29 04:01:13Closed
    sharing-torrents.comview history2010-03-29 03:58:14Closed
    slosoul.netview history2010-03-29 03:51:00Closed
    snowtigers.netview history2010-03-29 03:49:43Closed
    softmp3.orgview history2010-03-29 04:18:02Closed
    softmupparna.netview history2010-03-29 04:31:05Closed
    sounddamage.comview history2010-03-29 03:49:14Closed
    spanishtracker.comview history2010-03-29 04:25:07Open
    spank-d-monkey.comview history2010-03-29 04:17:09Closed
    special.pwtorrents.netview history2010-03-29 03:56:06Closed
    speed.cdview history2010-03-29 03:52:02Closed
    spiryt.ath.cxview history2010-03-29 04:12:07Closed
    sport-scene.netview history2010-03-29 03:55:15Closed
    sportbit.orgview history2010-03-29 04:25:08Closed
    sportleech.netview history2010-03-29 04:28:08Closed
    stmusic.orgview history2010-03-29 04:05:04Open
    supertorrents.orgview history2010-03-29 04:05:08Open
    swebits.orgview history2010-03-29 04:15:05Closed
    sweninjaz.orgview history2010-03-29 04:32:02Closed
    swep2p.orgview history2010-03-29 03:51:52Closed
    swepiracy.orgview history2010-03-29 04:05:07Open
    swetorrents.no-ip.orgview history2010-03-29 04:31:05Closed
    taiphimhd.comview history2010-03-29 03:55:07Closed
    tastetherainbow.wsview history2010-03-29 04:00:04Closed
    teamofgreekz.comview history2010-03-29 04:18:03Closed
    tehconnection.euview history2010-03-29 04:28:06Closed
    the-zomb.comview history2010-03-29 04:08:55Open
    thebox.bzview history2010-03-29 03:51:06Open
    thedvdclub.orgview history2010-03-29 04:25:07Open
    thegt.netview history2010-03-29 04:31:58Closed
    themixingbowl.orgview history2010-03-29 04:22:25Closed
    theoccult.bzview history2010-03-29 03:51:02Closed
    thepeerhub.comview history2010-03-29 04:00:12Open
    theplace.bzview history2010-03-29 04:08:56Closed
    thepokerbay.orgview history2010-03-29 03:59:37Open
    thevault.bzview history2010-03-29 03:59:39Closed
    titaniumtorrents.netview history2010-03-29 04:18:11Offline
    tmtorrents.orgview history2010-03-29 03:49:12Closed
    topbytes.netview history2010-03-29 03:49:08Closed
    topbytes.netview history2010-03-29 04:05:05Closed
    tophos.orgview history2010-03-29 03:58:09Closed
    torrent-damage.netview history2010-03-29 03:50:45Closed
    torrent.itview history2010-03-29 04:25:12Closed
    torrent411.comview history2010-03-29 04:15:08Open
    torrentbits.roview history2010-03-29 04:31:57Closed
    torrentbully.comview history2010-03-29 03:55:08Closed
    torrentdownloads.netview history2010-03-29 04:15:05Open
    torrentgaming.netview history2010-03-29 04:28:18Closed
    torrentgeeks.comview history2010-03-29 03:51:02Offline
    torrenthr.orgview history2010-03-29 04:21:10Open
    torrentkings.orgview history2010-03-29 03:49:05Closed
    torrentleech.orgview history2010-03-29 04:01:09Closed
    torrentseed.orgview history2010-03-29 03:56:10Closed
    torrentsforall.netview history2010-03-29 04:15:07Open
    torrentsmd.comview history2010-03-29 04:00:09Closed
    torrentvault.orgview history2010-03-29 03:49:12Closed
    torrentzilla.orgview history2010-03-29 03:57:04Open
    torrentzone.netview history2010-03-29 04:18:03Open
    totaltorrents.comview history2010-03-29 04:05:05Closed
    trancebits.comview history2010-03-29 04:25:09Closed
    trancebooster.netview history2010-03-29 04:05:03Closed
    trancetraffic.comview history2010-03-29 04:12:10Closed
    tri-tavern.comview history2010-03-29 04:17:07Closed
    tribalmixes.comview history2010-03-29 04:15:07Open
    tugaleech.comview history2010-03-29 03:59:05Closed
    tunebully.comview history2010-03-29 04:25:09Closed
    tv.torrents.roview history2010-03-29 03:58:06Closed
    tvtorrents.comview history2010-03-29 04:18:05Open
    ugstorrents.comview history2010-03-29 04:28:11Closed
    uknova.comview history2010-03-29 04:22:26Closed
    underground-gamer.comview history2010-03-29 04:17:07Open
    victorrent.netview history2010-03-29 04:01:09Closed
    vortexnetwork.orgview history2010-03-29 03:56:08Offline
    waffles.fmview history2010-03-29 03:56:11Closed
    wantedfiles.roview history2010-03-29 04:18:06Open
    warezbros.orgview history2010-03-29 04:08:59Closed
    what.cdview history2010-03-29 04:22:27Closed
    wild-bytes.orgview history2010-03-29 04:12:07Closed
    wolfbits.orgview history2010-03-29 04:22:07Closed
    worldboxingvideoarchive.comview history2010-03-29 04:05:06Open
    www.bt-pt.netview history2010-03-29 03:56:05Open
    www.llywot.comview history2010-03-29 03:59:38Closed
    xbitz.orgview history2010-03-29 04:18:14Open
    xider.huview history2010-03-29 04:05:02Open
    xtremespeeds.netview history2010-03-29 04:01:04Closed
    xtremewrestlingtorrents.netview history2010-03-29 03:51:05Closed
    xtremezone.roview history2010-03-29 03:58:08Closed
    yuwabits.netview history2010-03-29 04:05:07Open
    zanettetorrent.comview history2010-03-29 04:00:10Open
    zinebytes.orgview history2010-03-29 04:25:10Closed
    +
    +


    + + + +
    + + + + + + diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker2.html.51378~ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker2.html.51378~ new file mode 100644 index 0000000..e000284 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker2.html.51378~ @@ -0,0 +1,2948 @@ + + + +www.trackerchecker.com - We check your trackers + + + + + + +
    + + + + + + + +
    Home || Add a tracker || Latest trackers
    +
    + + +
    +follow us on Twitter
    +Follow trackerchecker on Twitter --> @trackerchecker. +
    + +
    + + +
    +
    + TrackerList
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     TrackerNameHistoryLastCheckedStatus
    1337x.orgview history2010-03-29 03:56:03Open
    420project.orgview history2010-03-29 04:28:13Closed
    acehd.netview history2010-03-29 04:31:58Closed
    acetorrents.netview history2010-03-29 03:59:08Open
    adult-cinema-network.netview history2010-03-29 04:00:08Open
    all4nothin.netview history2010-03-29 04:01:08Open
    allgirltorrents.comview history2010-03-29 03:50:57Closed
    allotracker.comview history2010-03-29 03:58:09Open
    appz.bitshock.orgview history2010-03-29 03:57:12Open
    appzuniverse.orgview history2010-03-29 04:18:04Closed
    arabfilms.orgview history2010-03-29 04:08:50Closed
    arabseries.orgview history2010-03-29 03:59:39Closed
    araditracker.comview history2010-03-29 04:22:25Closed
    arena-tr.comview history2010-03-29 04:12:10Closed
    arenabg.comview history2010-03-29 03:51:00Closed
    artofmisdirection.comview history2010-03-29 04:01:04Closed
    asiandvdclub.orgview history2010-03-29 04:18:15Open
    at-tracker.orgview history2010-03-29 04:15:08Offline
    atomico-torrent.comview history2010-03-29 03:56:05Closed
    audionews.ruview history2010-03-29 04:01:02Closed
    audiotracer.comview history2010-03-29 04:05:08Closed
    audiozonetorrents.comview history2010-03-29 03:56:09Open
    avatarbg.infoview history2010-03-29 03:49:14Closed
    awesome-hd.comview history2010-03-29 03:51:07Closed
    awesome-hd.netview history2010-03-29 03:55:09Closed
    baltracker.netview history2010-03-29 04:15:09Open
    bestmmatorrents.comview history2010-03-29 04:15:04Closed
    bestshare.roview history2010-03-29 03:56:11Closed
    bestxvid.orgview history2010-03-29 03:50:57Closed
    bit-hdtv.comview history2010-03-29 03:58:10Closed
    bitaddict.orgview history2010-03-29 03:50:45Closed
    bitchil.comview history2010-03-29 03:56:09Open
    bitflamers.comview history2010-03-29 04:01:12Closed
    bitgamer.comview history2010-03-29 04:12:08Closed
    bithq.orgview history2010-03-29 03:58:08Open
    bithumen.ath.cxview history2010-03-29 04:22:20Closed
    bitlove.huview history2010-03-29 04:25:10Closed
    bitme.orgview history2010-03-29 04:12:06Closed
    bitmetv.orgview history2010-03-29 03:49:16Closed
    bitmusic.huview history2010-03-29 03:58:11Closed
    bitnation.comview history2010-03-29 03:59:08Closed
    bitseduce.comview history2010-03-29 04:05:08Closed
    bitseek.orgview history2010-03-29 04:28:05Closed
    bitseek.orgview history2010-03-29 04:18:05Closed
    bitshock.orgview history2010-03-29 04:00:03Open
    bitshock.orgview history2010-03-29 03:55:14Closed
    bitsoup.orgview history2010-03-29 03:59:07Open
    bitSpyder.netview history2010-03-29 03:56:06Closed
    bittorrents.roview history2010-03-29 04:00:14Closed
    bitturk.netview history2010-03-29 03:56:05Closed
    biztorrents.comview history2010-03-29 04:15:07Open
    blackcats-games.netview history2010-03-29 03:58:06Closed
    blades-heaven.comview history2010-03-29 04:08:56Open
    blue-bytez.comview history2010-03-29 04:32:01Closed
    blue-whitegt.comview history2010-03-29 04:28:13Closed
    bmtorrents.netview history2010-03-29 03:58:10Closed
    bootytape.comview history2010-03-29 03:58:02Open
    bootytorrents.comview history2010-03-29 03:57:07Closed
    boxtorrents.comview history2010-03-29 04:08:59Closed
    bt.avistaz.comview history2010-03-29 04:15:08Closed
    bt.davka.infoview history2010-03-29 04:08:50Open
    bt.xbox-sky.ccview history2010-03-29 03:49:08Closed
    bt.xbox-sky.comview history2010-03-29 03:50:42Closed
    btgigs.infoview history2010-03-29 04:18:15Closed
    bwtorrents.comview history2010-03-29 03:56:10Closed
    bytelist.orgview history2010-03-29 04:05:07Offline
    cartoonchaos.orgview history2010-03-29 04:18:15Closed
    ccfbits.orgview history2010-03-29 04:22:19Closed
    chdbits.orgview history2010-03-29 04:15:11Closed
    cheggit.net/view history2010-03-29 04:09:00Open
    chilebt.comview history2010-03-29 04:22:11Closed
    christiantorrents.comview history2010-03-29 04:28:13Closed
    chronictracker.comview history2010-03-29 04:01:13Closed
    cinema-obscura.comview history2010-03-29 03:57:06Closed
    cinemageddon.orgview history2010-03-29 04:22:27Closed
    cinematik.netview history2010-03-29 03:57:11Closed
    cleanvobs.orgview history2010-03-29 03:49:43Closed
    colombo-bt.orgview history2010-03-29 03:50:55Closed
    contego.wsview history2010-03-29 04:22:12Closed
    crazytorrent.euview history2010-03-29 04:08:49Closed
    czone.roview history2010-03-29 04:24:09Closed
    danger.lvview history2010-03-29 03:55:15Closed
    demonoid.comview history2010-03-29 04:18:15Closed
    devilwolfs.comview history2010-03-29 04:31:55Closed
    diablotorrent.huview history2010-03-29 03:56:01Closed
    dididave.comview history2010-03-29 04:00:03Closed
    digitalhive.orgview history2010-03-29 03:50:44Closed
    dimeadozen.orgview history2010-03-29 04:05:06Open
    dnbtracker.orgview history2010-03-29 04:01:11Open
    docs.torrents.roview history2010-03-29 04:01:14Closed
    dvdseed.orgview history2010-03-29 04:32:01Closed
    dvdtreasure.euview history2010-03-29 04:05:04Closed
    ebookvortex.comview history2010-03-29 04:05:07Open
    eclipsetorrents.orgview history2010-03-29 04:12:09Closed
    egytorrent.comview history2010-03-29 03:49:06Closed
    egytorrent.comview history2010-03-29 04:01:05Closed
    elbitz.netview history2010-03-29 04:18:13Closed
    elektronik.roview history2010-03-29 03:55:02Closed
    empornium.usview history2010-03-29 03:57:07Open
    eroticsource.plview history2010-03-29 04:28:19Closed
    estrenoslatinos.comview history2010-03-29 03:49:10Closed
    ethor.netview history2010-03-29 03:51:08Closed
    evopt.orgview history2010-03-29 04:15:06Closed
    Exigomusicview history2010-03-29 03:50:45Closed
    extremebits.orgview history2010-03-29 04:28:05Closed
    extremeshare.orgview history2010-03-29 03:59:03Open
    faplife.netview history2010-03-29 03:50:46Closed
    feedthe.netview history2010-03-29 04:22:09Closed
    filebits.orgview history2010-03-29 03:57:08Closed
    filelist.orgview history2010-03-29 04:22:25Closed
    filelist.roview history2010-03-29 03:56:09Closed
    filemp3.orgview history2010-03-29 03:50:46Closed
    fileporn.orgview history2010-03-29 03:51:10Closed
    flashtorrents.com.arview history2010-03-29 03:59:40Closed
    Free The Scene (FTS)view history2010-03-29 04:05:04Closed
    Fresh On TV (TvT)view history2010-03-29 03:59:37Open
    frztracker.sytes.netview history2010-03-29 04:25:08Closed
    fst.omnilounge.co.ukview history2010-03-29 04:08:50Closed
    fullcontactzone.comview history2010-03-29 03:56:09Closed
    gamecrook.comview history2010-03-29 04:18:05Closed
    gbvnet.roview history2010-03-29 04:25:08Open
    gettorrents.orgview history2010-03-29 04:11:06Closed
    gfxnews.ruview history2010-03-29 04:12:07Closed
    gigatorrents.wsview history2010-03-29 03:57:05Closed
    globus-tracker.comview history2010-03-29 04:30:51Closed
    goem.orgview history2010-03-29 03:56:07Closed
    gormogon.comview history2010-03-29 04:25:05Open
    greek-tracker.comview history2010-03-29 03:51:06Closed
    grimetorrent.comview history2010-03-29 04:28:15Closed
    grtorrent.comview history2010-03-29 04:12:08Closed
    guiks.netview history2010-03-29 04:05:04Closed
    h264torrents.comview history2010-03-29 03:57:01Closed
    h33t.comview history2010-03-29 03:51:06Open
    hd-bits.roview history2010-03-29 04:18:09Closed
    hd-torrents.orgview history2010-03-29 04:05:05Closed
    hdbits.orgview history2010-03-29 04:12:07Closed
    hdchina.orgview history2010-03-29 03:59:37Closed
    hdfrench.comview history2010-03-29 04:09:01Closed
    hdme.euview history2010-03-29 03:55:09Open
    hdpre.comview history2010-03-29 04:12:09Closed
    hdsource.bizview history2010-03-29 03:49:13Closed
    hdstar.orgview history2010-03-29 03:51:02Closed
    hdvnbits.orgview history2010-03-29 03:56:03Closed
    heaventracker.orgview history2010-03-29 03:57:02Closed
    hermeticos.orgview history2010-03-29 04:25:12Closed
    horrorcharnel.kicks-ass.orgview history2010-03-29 03:58:05Closed
    hungercity.orgview history2010-03-29 04:31:05Open
    ifyounotknow.comview history2010-03-29 03:58:07Closed
    ilovetorrents.comview history2010-03-29 03:56:06Open
    indeep.bizview history2010-03-29 03:56:08Closed
    indietorrents.comview history2010-03-29 04:00:14Closed
    iplay.roview history2010-03-29 03:59:03Closed
    ipodnova.tvview history2010-03-29 04:04:12Closed
    iptorrents.comview history2010-03-29 03:51:06Closed
    joompalace.comview history2010-03-29 03:57:04Closed
    karagarga.netview history2010-03-29 04:17:07Closed
    killawaves.netview history2010-03-29 04:05:05Closed
    kinozal.wsview history2010-03-29 04:28:16Open
    kludd.comview history2010-03-29 03:55:11Closed
    lasttorrents.orgview history2010-03-29 04:32:02Open
    leecherslair.comview history2010-03-29 04:18:08Closed
    libble.comview history2010-03-29 04:25:11Closed
    libitina.netview history2010-03-29 04:18:11Closed
    linuxmafia.netview history2010-03-29 04:22:07Offline
    linuxtracker.orgview history2010-03-29 04:22:24Closed
    lostfilm.tvview history2010-03-29 04:00:07Open
    magiciantorrents.comview history2010-03-29 03:55:14Closed
    masterstb.comview history2010-03-29 03:56:12Closed
    mazetorrents.netview history2010-03-29 04:17:07Offline
    medioteka.comview history2010-03-29 04:17:07Closed
    mega-bits.comview history2010-03-29 03:51:52Closed
    mentol.roview history2010-03-29 04:12:04Closed
    metal.iplay.roview history2010-03-29 04:18:03Closed
    metalbits.orgview history2010-03-29 04:00:02Closed
    midnight-scene.comview history2010-03-29 03:58:06Closed
    midnight-torrents.comview history2010-03-29 04:31:05Closed
    mma-central.org.ukview history2010-03-29 03:56:05Closed
    mma-tracker.netview history2010-03-29 03:50:43Closed
    mp3nerds.orgview history2010-03-29 04:18:07Closed
    mucis-vid.comview history2010-03-29 03:56:06Closed
    musicplace.lvview history2010-03-29 04:05:04Closed
    mytorrent.tvview history2010-03-29 03:57:07Closed
    norbits.netview history2010-03-29 04:12:05Closed
    nordic-t.orgview history2010-03-29 03:55:02Closed
    nordicbits.orgview history2010-03-29 04:18:07Offline
    novaro.infoview history2010-03-29 03:49:16Closed
    novaro.infoview history2010-03-29 03:55:02Closed
    noviteti.comview history2010-03-29 04:15:05Offline
    ntorrents.netview history2010-03-29 03:59:08Closed
    nutorrent.comview history2010-03-29 04:25:12Open
    opennetwork.roview history2010-03-29 04:08:49Closed
    overtopropetorrents.comview history2010-03-29 04:00:14Closed
    ozone-torrents.orgview history2010-03-29 04:32:00Closed
    Pedros btmusicview history2010-03-29 04:08:54Closed
    pianosheets.orgview history2010-03-29 03:49:17Closed
    pinkytorrents.comview history2010-03-29 03:56:08Open
    piranha.excom.usview history2010-03-29 04:08:07Open
    Pirate The Net (PtN)view history2010-03-29 03:49:15Closed
    piratebits.orgview history2010-03-29 04:09:01Closed
    piratefiles.seview history2010-03-29 04:25:05Closed
    piratetorrents.nuview history2010-03-29 03:56:04Closed
    pisexy.orgview history2010-03-29 04:01:06Closed
    polishbytes.netview history2010-03-29 04:31:55Open
    polishtracker.orgview history2010-03-29 03:56:09Closed
    pornbay.orgview history2010-03-29 03:57:12Closed
    PotUKview history2010-03-29 04:08:54Closed
    powerscene.orgview history2010-03-29 03:57:11Closed
    pretome.netview history2010-03-29 04:32:01Closed
    proaudiotorrents.orgview history2010-03-29 04:15:14Closed
    psytorrents.infoview history2010-03-29 03:49:08Closed
    ptfiles.orgview history2010-03-29 04:18:09Closed
    punkhc.dyndns.orgview history2010-03-29 04:01:09Closed
    puretna.comview history2010-03-29 04:05:06Open
    pussytorrents.orgview history2010-03-29 03:52:02Open
    rapthe.netview history2010-03-29 04:12:09Closed
    rarbg.comview history2010-03-29 03:58:11Open
    reload-paradise.netview history2010-03-29 04:00:07Closed
    revolutiontt.netview history2010-03-29 03:56:07Closed
    rmvbustersview history2010-03-29 04:15:08Open
    rmvbusters.plview history2010-03-29 03:56:05Open
    scaliwags.orgview history2010-03-29 03:59:04Closed
    scene-gold.infoview history2010-03-29 04:17:08Offline
    scene-inspired.comview history2010-03-29 03:51:07Open
    sceneaccess.orgview history2010-03-29 03:55:09Closed
    scenebytes.clview history2010-03-29 04:22:20Closed
    scenehd.orgview history2010-03-29 04:28:09Closed
    sceneleech.orgview history2010-03-29 03:57:05Closed
    SceneLife (ScL)view history2010-03-29 04:00:08Closed
    scenetorrents.orgview history2010-03-29 04:12:05Closed
    scenetuga.orgview history2010-03-29 03:51:04Closed
    sciencehd.netview history2010-03-29 04:00:15Closed
    scifitorrents.netview history2010-03-29 03:56:10Closed
    secret-cinema.netview history2010-03-29 04:28:13Closed
    seedgames.orgview history2010-03-29 04:18:16Closed
    seedmore.orgview history2010-03-29 03:56:11Closed
    sharetorrents.plview history2010-03-29 04:01:13Closed
    sharing-torrents.comview history2010-03-29 03:58:14Closed
    slosoul.netview history2010-03-29 03:51:00Closed
    snowtigers.netview history2010-03-29 03:49:43Closed
    softmp3.orgview history2010-03-29 04:18:02Closed
    softmupparna.netview history2010-03-29 04:31:05Closed
    sounddamage.comview history2010-03-29 03:49:14Closed
    spanishtracker.comview history2010-03-29 04:25:07Open
    spank-d-monkey.comview history2010-03-29 04:17:09Closed
    special.pwtorrents.netview history2010-03-29 03:56:06Closed
    speed.cdview history2010-03-29 03:52:02Closed
    spiryt.ath.cxview history2010-03-29 04:12:07Closed
    sport-scene.netview history2010-03-29 03:55:15Closed
    sportbit.orgview history2010-03-29 04:25:08Closed
    sportleech.netview history2010-03-29 04:28:08Closed
    stmusic.orgview history2010-03-29 04:05:04Open
    supertorrents.orgview history2010-03-29 04:05:08Open
    swebits.orgview history2010-03-29 04:15:05Closed
    sweninjaz.orgview history2010-03-29 04:32:02Closed
    swep2p.orgview history2010-03-29 03:51:52Closed
    swepiracy.orgview history2010-03-29 04:05:07Open
    swetorrents.no-ip.orgview history2010-03-29 04:31:05Closed
    taiphimhd.comview history2010-03-29 03:55:07Closed
    tastetherainbow.wsview history2010-03-29 04:00:04Closed
    teamofgreekz.comview history2010-03-29 04:18:03Closed
    tehconnection.euview history2010-03-29 04:28:06Closed
    the-zomb.comview history2010-03-29 04:08:55Open
    thebox.bzview history2010-03-29 03:51:06Open
    thedvdclub.orgview history2010-03-29 04:25:07Open
    thegt.netview history2010-03-29 04:31:58Closed
    themixingbowl.orgview history2010-03-29 04:22:25Closed
    theoccult.bzview history2010-03-29 03:51:02Closed
    thepeerhub.comview history2010-03-29 04:00:12Open
    theplace.bzview history2010-03-29 04:08:56Closed
    thepokerbay.orgview history2010-03-29 03:59:37Open
    thevault.bzview history2010-03-29 03:59:39Closed
    titaniumtorrents.netview history2010-03-29 04:18:11Offline
    tmtorrents.orgview history2010-03-29 03:49:12Closed
    topbytes.netview history2010-03-29 03:49:08Closed
    topbytes.netview history2010-03-29 04:05:05Closed
    tophos.orgview history2010-03-29 03:58:09Closed
    torrent-damage.netview history2010-03-29 03:50:45Closed
    torrent.itview history2010-03-29 04:25:12Closed
    torrent411.comview history2010-03-29 04:15:08Open
    torrentbits.roview history2010-03-29 04:31:57Closed
    torrentbully.comview history2010-03-29 03:55:08Closed
    torrentdownloads.netview history2010-03-29 04:15:05Open
    torrentgaming.netview history2010-03-29 04:28:18Closed
    torrentgeeks.comview history2010-03-29 03:51:02Offline
    torrenthr.orgview history2010-03-29 04:21:10Open
    torrentkings.orgview history2010-03-29 03:49:05Closed
    torrentleech.orgview history2010-03-29 04:01:09Closed
    torrentseed.orgview history2010-03-29 03:56:10Closed
    torrentsforall.netview history2010-03-29 04:15:07Open
    torrentsmd.comview history2010-03-29 04:00:09Closed
    torrentvault.orgview history2010-03-29 03:49:12Closed
    torrentzilla.orgview history2010-03-29 03:57:04Open
    torrentzone.netview history2010-03-29 04:18:03Open
    totaltorrents.comview history2010-03-29 04:05:05Closed
    trancebits.comview history2010-03-29 04:25:09Closed
    trancebooster.netview history2010-03-29 04:05:03Closed
    trancetraffic.comview history2010-03-29 04:12:10Closed
    tri-tavern.comview history2010-03-29 04:17:07Closed
    tribalmixes.comview history2010-03-29 04:15:07Open
    tugaleech.comview history2010-03-29 03:59:05Closed
    tunebully.comview history2010-03-29 04:25:09Closed
    tv.torrents.roview history2010-03-29 03:58:06Closed
    tvtorrents.comview history2010-03-29 04:18:05Open
    ugstorrents.comview history2010-03-29 04:28:11Closed
    uknova.comview history2010-03-29 04:22:26Closed
    underground-gamer.comview history2010-03-29 04:17:07Open
    victorrent.netview history2010-03-29 04:01:09Closed
    vortexnetwork.orgview history2010-03-29 03:56:08Offline
    waffles.fmview history2010-03-29 03:56:11Closed
    wantedfiles.roview history2010-03-29 04:18:06Open
    warezbros.orgview history2010-03-29 04:08:59Closed
    what.cdview history2010-03-29 04:22:27Closed
    wild-bytes.orgview history2010-03-29 04:12:07Closed
    wolfbits.orgview history2010-03-29 04:22:07Closed
    worldboxingvideoarchive.comview history2010-03-29 04:05:06Open
    www.bt-pt.netview history2010-03-29 03:56:05Open
    www.llywot.comview history2010-03-29 03:59:38Closed
    xbitz.orgview history2010-03-29 04:18:14Open
    xider.huview history2010-03-29 04:05:02Open
    xtremespeeds.netview history2010-03-29 04:01:04Closed
    xtremewrestlingtorrents.netview history2010-03-29 03:51:05Closed
    xtremezone.roview history2010-03-29 03:58:08Closed
    yuwabits.netview history2010-03-29 04:05:07Open
    zanettetorrent.comview history2010-03-29 04:00:10Open
    zinebytes.orgview history2010-03-29 04:25:10Closed
    +
    +


    + + + +
    + + + + + + diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker2.html.75287~ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker2.html.75287~ new file mode 100644 index 0000000..1eea80d --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/.tmp_trackerchecker2.html.75287~ @@ -0,0 +1,2947 @@ + + +www.trackerchecker.com - We check your trackers + + + + + + +
    + + + + + + + +
    Home || Add a tracker || Latest trackers
    +
    + + +
    +follow us on Twitter
    +Follow trackerchecker on Twitter --> @trackerchecker. +
    + +
    + + +
    +
    + TrackerList
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     TrackerNameHistoryLastCheckedStatus
    1337x.orgview history2010-03-29 03:56:03Open
    420project.orgview history2010-03-29 04:28:13Closed
    acehd.netview history2010-03-29 04:31:58Closed
    acetorrents.netview history2010-03-29 03:59:08Open
    adult-cinema-network.netview history2010-03-29 04:00:08Open
    all4nothin.netview history2010-03-29 04:01:08Open
    allgirltorrents.comview history2010-03-29 03:50:57Closed
    allotracker.comview history2010-03-29 03:58:09Open
    appz.bitshock.orgview history2010-03-29 03:57:12Open
    appzuniverse.orgview history2010-03-29 04:18:04Closed
    arabfilms.orgview history2010-03-29 04:08:50Closed
    arabseries.orgview history2010-03-29 03:59:39Closed
    araditracker.comview history2010-03-29 04:22:25Closed
    arena-tr.comview history2010-03-29 04:12:10Closed
    arenabg.comview history2010-03-29 03:51:00Closed
    artofmisdirection.comview history2010-03-29 04:01:04Closed
    asiandvdclub.orgview history2010-03-29 04:18:15Open
    at-tracker.orgview history2010-03-29 04:15:08Offline
    atomico-torrent.comview history2010-03-29 03:56:05Closed
    audionews.ruview history2010-03-29 04:01:02Closed
    audiotracer.comview history2010-03-29 04:05:08Closed
    audiozonetorrents.comview history2010-03-29 03:56:09Open
    avatarbg.infoview history2010-03-29 03:49:14Closed
    awesome-hd.comview history2010-03-29 03:51:07Closed
    awesome-hd.netview history2010-03-29 03:55:09Closed
    baltracker.netview history2010-03-29 04:15:09Open
    bestmmatorrents.comview history2010-03-29 04:15:04Closed
    bestshare.roview history2010-03-29 03:56:11Closed
    bestxvid.orgview history2010-03-29 03:50:57Closed
    bit-hdtv.comview history2010-03-29 03:58:10Closed
    bitaddict.orgview history2010-03-29 03:50:45Closed
    bitchil.comview history2010-03-29 03:56:09Open
    bitflamers.comview history2010-03-29 04:01:12Closed
    bitgamer.comview history2010-03-29 04:12:08Closed
    bithq.orgview history2010-03-29 03:58:08Open
    bithumen.ath.cxview history2010-03-29 04:22:20Closed
    bitlove.huview history2010-03-29 04:25:10Closed
    bitme.orgview history2010-03-29 04:12:06Closed
    bitmetv.orgview history2010-03-29 03:49:16Closed
    bitmusic.huview history2010-03-29 03:58:11Closed
    bitnation.comview history2010-03-29 03:59:08Closed
    bitseduce.comview history2010-03-29 04:05:08Closed
    bitseek.orgview history2010-03-29 04:28:05Closed
    bitseek.orgview history2010-03-29 04:18:05Closed
    bitshock.orgview history2010-03-29 04:00:03Open
    bitshock.orgview history2010-03-29 03:55:14Closed
    bitsoup.orgview history2010-03-29 03:59:07Open
    bitSpyder.netview history2010-03-29 03:56:06Closed
    bittorrents.roview history2010-03-29 04:00:14Closed
    bitturk.netview history2010-03-29 03:56:05Closed
    biztorrents.comview history2010-03-29 04:15:07Open
    blackcats-games.netview history2010-03-29 03:58:06Closed
    blades-heaven.comview history2010-03-29 04:08:56Open
    blue-bytez.comview history2010-03-29 04:32:01Closed
    blue-whitegt.comview history2010-03-29 04:28:13Closed
    bmtorrents.netview history2010-03-29 03:58:10Closed
    bootytape.comview history2010-03-29 03:58:02Open
    bootytorrents.comview history2010-03-29 03:57:07Closed
    boxtorrents.comview history2010-03-29 04:08:59Closed
    bt.avistaz.comview history2010-03-29 04:15:08Closed
    bt.davka.infoview history2010-03-29 04:08:50Open
    bt.xbox-sky.ccview history2010-03-29 03:49:08Closed
    bt.xbox-sky.comview history2010-03-29 03:50:42Closed
    btgigs.infoview history2010-03-29 04:18:15Closed
    bwtorrents.comview history2010-03-29 03:56:10Closed
    bytelist.orgview history2010-03-29 04:05:07Offline
    cartoonchaos.orgview history2010-03-29 04:18:15Closed
    ccfbits.orgview history2010-03-29 04:22:19Closed
    chdbits.orgview history2010-03-29 04:15:11Closed
    cheggit.net/view history2010-03-29 04:09:00Open
    chilebt.comview history2010-03-29 04:22:11Closed
    christiantorrents.comview history2010-03-29 04:28:13Closed
    chronictracker.comview history2010-03-29 04:01:13Closed
    cinema-obscura.comview history2010-03-29 03:57:06Closed
    cinemageddon.orgview history2010-03-29 04:22:27Closed
    cinematik.netview history2010-03-29 03:57:11Closed
    cleanvobs.orgview history2010-03-29 03:49:43Closed
    colombo-bt.orgview history2010-03-29 03:50:55Closed
    contego.wsview history2010-03-29 04:22:12Closed
    crazytorrent.euview history2010-03-29 04:08:49Closed
    czone.roview history2010-03-29 04:24:09Closed
    danger.lvview history2010-03-29 03:55:15Closed
    demonoid.comview history2010-03-29 04:18:15Closed
    devilwolfs.comview history2010-03-29 04:31:55Closed
    diablotorrent.huview history2010-03-29 03:56:01Closed
    dididave.comview history2010-03-29 04:00:03Closed
    digitalhive.orgview history2010-03-29 03:50:44Closed
    dimeadozen.orgview history2010-03-29 04:05:06Open
    dnbtracker.orgview history2010-03-29 04:01:11Open
    docs.torrents.roview history2010-03-29 04:01:14Closed
    dvdseed.orgview history2010-03-29 04:32:01Closed
    dvdtreasure.euview history2010-03-29 04:05:04Closed
    ebookvortex.comview history2010-03-29 04:05:07Open
    eclipsetorrents.orgview history2010-03-29 04:12:09Closed
    egytorrent.comview history2010-03-29 03:49:06Closed
    egytorrent.comview history2010-03-29 04:01:05Closed
    elbitz.netview history2010-03-29 04:18:13Closed
    elektronik.roview history2010-03-29 03:55:02Closed
    empornium.usview history2010-03-29 03:57:07Open
    eroticsource.plview history2010-03-29 04:28:19Closed
    estrenoslatinos.comview history2010-03-29 03:49:10Closed
    ethor.netview history2010-03-29 03:51:08Closed
    evopt.orgview history2010-03-29 04:15:06Closed
    Exigomusicview history2010-03-29 03:50:45Closed
    extremebits.orgview history2010-03-29 04:28:05Closed
    extremeshare.orgview history2010-03-29 03:59:03Open
    faplife.netview history2010-03-29 03:50:46Closed
    feedthe.netview history2010-03-29 04:22:09Closed
    filebits.orgview history2010-03-29 03:57:08Closed
    filelist.orgview history2010-03-29 04:22:25Closed
    filelist.roview history2010-03-29 03:56:09Closed
    filemp3.orgview history2010-03-29 03:50:46Closed
    fileporn.orgview history2010-03-29 03:51:10Closed
    flashtorrents.com.arview history2010-03-29 03:59:40Closed
    Free The Scene (FTS)view history2010-03-29 04:05:04Closed
    Fresh On TV (TvT)view history2010-03-29 03:59:37Open
    frztracker.sytes.netview history2010-03-29 04:25:08Closed
    fst.omnilounge.co.ukview history2010-03-29 04:08:50Closed
    fullcontactzone.comview history2010-03-29 03:56:09Closed
    gamecrook.comview history2010-03-29 04:18:05Closed
    gbvnet.roview history2010-03-29 04:25:08Open
    gettorrents.orgview history2010-03-29 04:11:06Closed
    gfxnews.ruview history2010-03-29 04:12:07Closed
    gigatorrents.wsview history2010-03-29 03:57:05Closed
    globus-tracker.comview history2010-03-29 04:30:51Closed
    goem.orgview history2010-03-29 03:56:07Closed
    gormogon.comview history2010-03-29 04:25:05Open
    greek-tracker.comview history2010-03-29 03:51:06Closed
    grimetorrent.comview history2010-03-29 04:28:15Closed
    grtorrent.comview history2010-03-29 04:12:08Closed
    guiks.netview history2010-03-29 04:05:04Closed
    h264torrents.comview history2010-03-29 03:57:01Closed
    h33t.comview history2010-03-29 03:51:06Open
    hd-bits.roview history2010-03-29 04:18:09Closed
    hd-torrents.orgview history2010-03-29 04:05:05Closed
    hdbits.orgview history2010-03-29 04:12:07Closed
    hdchina.orgview history2010-03-29 03:59:37Closed
    hdfrench.comview history2010-03-29 04:09:01Closed
    hdme.euview history2010-03-29 03:55:09Open
    hdpre.comview history2010-03-29 04:12:09Closed
    hdsource.bizview history2010-03-29 03:49:13Closed
    hdstar.orgview history2010-03-29 03:51:02Closed
    hdvnbits.orgview history2010-03-29 03:56:03Closed
    heaventracker.orgview history2010-03-29 03:57:02Closed
    hermeticos.orgview history2010-03-29 04:25:12Closed
    horrorcharnel.kicks-ass.orgview history2010-03-29 03:58:05Closed
    hungercity.orgview history2010-03-29 04:31:05Open
    ifyounotknow.comview history2010-03-29 03:58:07Closed
    ilovetorrents.comview history2010-03-29 03:56:06Open
    indeep.bizview history2010-03-29 03:56:08Closed
    indietorrents.comview history2010-03-29 04:00:14Closed
    iplay.roview history2010-03-29 03:59:03Closed
    ipodnova.tvview history2010-03-29 04:04:12Closed
    iptorrents.comview history2010-03-29 03:51:06Closed
    joompalace.comview history2010-03-29 03:57:04Closed
    karagarga.netview history2010-03-29 04:17:07Closed
    killawaves.netview history2010-03-29 04:05:05Closed
    kinozal.wsview history2010-03-29 04:28:16Open
    kludd.comview history2010-03-29 03:55:11Closed
    lasttorrents.orgview history2010-03-29 04:32:02Open
    leecherslair.comview history2010-03-29 04:18:08Closed
    libble.comview history2010-03-29 04:25:11Closed
    libitina.netview history2010-03-29 04:18:11Closed
    linuxmafia.netview history2010-03-29 04:22:07Offline
    linuxtracker.orgview history2010-03-29 04:22:24Closed
    lostfilm.tvview history2010-03-29 04:00:07Open
    magiciantorrents.comview history2010-03-29 03:55:14Closed
    masterstb.comview history2010-03-29 03:56:12Closed
    mazetorrents.netview history2010-03-29 04:17:07Offline
    medioteka.comview history2010-03-29 04:17:07Closed
    mega-bits.comview history2010-03-29 03:51:52Closed
    mentol.roview history2010-03-29 04:12:04Closed
    metal.iplay.roview history2010-03-29 04:18:03Closed
    metalbits.orgview history2010-03-29 04:00:02Closed
    midnight-scene.comview history2010-03-29 03:58:06Closed
    midnight-torrents.comview history2010-03-29 04:31:05Closed
    mma-central.org.ukview history2010-03-29 03:56:05Closed
    mma-tracker.netview history2010-03-29 03:50:43Closed
    mp3nerds.orgview history2010-03-29 04:18:07Closed
    mucis-vid.comview history2010-03-29 03:56:06Closed
    musicplace.lvview history2010-03-29 04:05:04Closed
    mytorrent.tvview history2010-03-29 03:57:07Closed
    norbits.netview history2010-03-29 04:12:05Closed
    nordic-t.orgview history2010-03-29 03:55:02Closed
    nordicbits.orgview history2010-03-29 04:18:07Offline
    novaro.infoview history2010-03-29 03:49:16Closed
    novaro.infoview history2010-03-29 03:55:02Closed
    noviteti.comview history2010-03-29 04:15:05Offline
    ntorrents.netview history2010-03-29 03:59:08Closed
    nutorrent.comview history2010-03-29 04:25:12Open
    opennetwork.roview history2010-03-29 04:08:49Closed
    overtopropetorrents.comview history2010-03-29 04:00:14Closed
    ozone-torrents.orgview history2010-03-29 04:32:00Closed
    Pedros btmusicview history2010-03-29 04:08:54Closed
    pianosheets.orgview history2010-03-29 03:49:17Closed
    pinkytorrents.comview history2010-03-29 03:56:08Open
    piranha.excom.usview history2010-03-29 04:08:07Open
    Pirate The Net (PtN)view history2010-03-29 03:49:15Closed
    piratebits.orgview history2010-03-29 04:09:01Closed
    piratefiles.seview history2010-03-29 04:25:05Closed
    piratetorrents.nuview history2010-03-29 03:56:04Closed
    pisexy.orgview history2010-03-29 04:01:06Closed
    polishbytes.netview history2010-03-29 04:31:55Open
    polishtracker.orgview history2010-03-29 03:56:09Closed
    pornbay.orgview history2010-03-29 03:57:12Closed
    PotUKview history2010-03-29 04:08:54Closed
    powerscene.orgview history2010-03-29 03:57:11Closed
    pretome.netview history2010-03-29 04:32:01Closed
    proaudiotorrents.orgview history2010-03-29 04:15:14Closed
    psytorrents.infoview history2010-03-29 03:49:08Closed
    ptfiles.orgview history2010-03-29 04:18:09Closed
    punkhc.dyndns.orgview history2010-03-29 04:01:09Closed
    puretna.comview history2010-03-29 04:05:06Open
    pussytorrents.orgview history2010-03-29 03:52:02Open
    rapthe.netview history2010-03-29 04:12:09Closed
    rarbg.comview history2010-03-29 03:58:11Open
    reload-paradise.netview history2010-03-29 04:00:07Closed
    revolutiontt.netview history2010-03-29 03:56:07Closed
    rmvbustersview history2010-03-29 04:15:08Open
    rmvbusters.plview history2010-03-29 03:56:05Open
    scaliwags.orgview history2010-03-29 03:59:04Closed
    scene-gold.infoview history2010-03-29 04:17:08Offline
    scene-inspired.comview history2010-03-29 03:51:07Open
    sceneaccess.orgview history2010-03-29 03:55:09Closed
    scenebytes.clview history2010-03-29 04:22:20Closed
    scenehd.orgview history2010-03-29 04:28:09Closed
    sceneleech.orgview history2010-03-29 03:57:05Closed
    SceneLife (ScL)view history2010-03-29 04:00:08Closed
    scenetorrents.orgview history2010-03-29 04:12:05Closed
    scenetuga.orgview history2010-03-29 03:51:04Closed
    sciencehd.netview history2010-03-29 04:00:15Closed
    scifitorrents.netview history2010-03-29 03:56:10Closed
    secret-cinema.netview history2010-03-29 04:28:13Closed
    seedgames.orgview history2010-03-29 04:18:16Closed
    seedmore.orgview history2010-03-29 03:56:11Closed
    sharetorrents.plview history2010-03-29 04:01:13Closed
    sharing-torrents.comview history2010-03-29 03:58:14Closed
    slosoul.netview history2010-03-29 03:51:00Closed
    snowtigers.netview history2010-03-29 03:49:43Closed
    softmp3.orgview history2010-03-29 04:18:02Closed
    softmupparna.netview history2010-03-29 04:31:05Closed
    sounddamage.comview history2010-03-29 03:49:14Closed
    spanishtracker.comview history2010-03-29 04:25:07Open
    spank-d-monkey.comview history2010-03-29 04:17:09Closed
    special.pwtorrents.netview history2010-03-29 03:56:06Closed
    speed.cdview history2010-03-29 03:52:02Closed
    spiryt.ath.cxview history2010-03-29 04:12:07Closed
    sport-scene.netview history2010-03-29 03:55:15Closed
    sportbit.orgview history2010-03-29 04:25:08Closed
    sportleech.netview history2010-03-29 04:28:08Closed
    stmusic.orgview history2010-03-29 04:05:04Open
    supertorrents.orgview history2010-03-29 04:05:08Open
    swebits.orgview history2010-03-29 04:15:05Closed
    sweninjaz.orgview history2010-03-29 04:32:02Closed
    swep2p.orgview history2010-03-29 03:51:52Closed
    swepiracy.orgview history2010-03-29 04:05:07Open
    swetorrents.no-ip.orgview history2010-03-29 04:31:05Closed
    taiphimhd.comview history2010-03-29 03:55:07Closed
    tastetherainbow.wsview history2010-03-29 04:00:04Closed
    teamofgreekz.comview history2010-03-29 04:18:03Closed
    tehconnection.euview history2010-03-29 04:28:06Closed
    the-zomb.comview history2010-03-29 04:08:55Open
    thebox.bzview history2010-03-29 03:51:06Open
    thedvdclub.orgview history2010-03-29 04:25:07Open
    thegt.netview history2010-03-29 04:31:58Closed
    themixingbowl.orgview history2010-03-29 04:22:25Closed
    theoccult.bzview history2010-03-29 03:51:02Closed
    thepeerhub.comview history2010-03-29 04:00:12Open
    theplace.bzview history2010-03-29 04:08:56Closed
    thepokerbay.orgview history2010-03-29 03:59:37Open
    thevault.bzview history2010-03-29 03:59:39Closed
    titaniumtorrents.netview history2010-03-29 04:18:11Offline
    tmtorrents.orgview history2010-03-29 03:49:12Closed
    topbytes.netview history2010-03-29 03:49:08Closed
    topbytes.netview history2010-03-29 04:05:05Closed
    tophos.orgview history2010-03-29 03:58:09Closed
    torrent-damage.netview history2010-03-29 03:50:45Closed
    torrent.itview history2010-03-29 04:25:12Closed
    torrent411.comview history2010-03-29 04:15:08Open
    torrentbits.roview history2010-03-29 04:31:57Closed
    torrentbully.comview history2010-03-29 03:55:08Closed
    torrentdownloads.netview history2010-03-29 04:15:05Open
    torrentgaming.netview history2010-03-29 04:28:18Closed
    torrentgeeks.comview history2010-03-29 03:51:02Offline
    torrenthr.orgview history2010-03-29 04:21:10Open
    torrentkings.orgview history2010-03-29 03:49:05Closed
    torrentleech.orgview history2010-03-29 04:01:09Closed
    torrentseed.orgview history2010-03-29 03:56:10Closed
    torrentsforall.netview history2010-03-29 04:15:07Open
    torrentsmd.comview history2010-03-29 04:00:09Closed
    torrentvault.orgview history2010-03-29 03:49:12Closed
    torrentzilla.orgview history2010-03-29 03:57:04Open
    torrentzone.netview history2010-03-29 04:18:03Open
    totaltorrents.comview history2010-03-29 04:05:05Closed
    trancebits.comview history2010-03-29 04:25:09Closed
    trancebooster.netview history2010-03-29 04:05:03Closed
    trancetraffic.comview history2010-03-29 04:12:10Closed
    tri-tavern.comview history2010-03-29 04:17:07Closed
    tribalmixes.comview history2010-03-29 04:15:07Open
    tugaleech.comview history2010-03-29 03:59:05Closed
    tunebully.comview history2010-03-29 04:25:09Closed
    tv.torrents.roview history2010-03-29 03:58:06Closed
    tvtorrents.comview history2010-03-29 04:18:05Open
    ugstorrents.comview history2010-03-29 04:28:11Closed
    uknova.comview history2010-03-29 04:22:26Closed
    underground-gamer.comview history2010-03-29 04:17:07Open
    victorrent.netview history2010-03-29 04:01:09Closed
    vortexnetwork.orgview history2010-03-29 03:56:08Offline
    waffles.fmview history2010-03-29 03:56:11Closed
    wantedfiles.roview history2010-03-29 04:18:06Open
    warezbros.orgview history2010-03-29 04:08:59Closed
    what.cdview history2010-03-29 04:22:27Closed
    wild-bytes.orgview history2010-03-29 04:12:07Closed
    wolfbits.orgview history2010-03-29 04:22:07Closed
    worldboxingvideoarchive.comview history2010-03-29 04:05:06Open
    www.bt-pt.netview history2010-03-29 03:56:05Open
    www.llywot.comview history2010-03-29 03:59:38Closed
    xbitz.orgview history2010-03-29 04:18:14Open
    xider.huview history2010-03-29 04:05:02Open
    xtremespeeds.netview history2010-03-29 04:01:04Closed
    xtremewrestlingtorrents.netview history2010-03-29 03:51:05Closed
    xtremezone.roview history2010-03-29 03:58:08Closed
    yuwabits.netview history2010-03-29 04:05:07Open
    zanettetorrent.comview history2010-03-29 04:00:10Open
    zinebytes.orgview history2010-03-29 04:25:10Closed
    +
    +


    + +--> + +
    + + + + + + diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/api.html b/node_modules/jsdom/node_modules/htmlparser/testdata/api.html new file mode 100644 index 0000000..e7a71c4 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/api.html @@ -0,0 +1,3311 @@ + + + + + node(1) -- evented I/O for V8 JavaScript + + + + + +
    +
    Node v0.1.99
    + +
    +
    +
    +

    node(1)

    + +
      +
    1. node(1)
    2. + +
    3. +
    4. node(1)
    5. +
    +

    NAME

    +

    node -- evented I/O for V8 JavaScript

    + +

    Synopsis

    + +

    An example of a web server written with Node which responds with 'Hello +World':

    + +
    var sys = require('sys'),
    +  http = require('http');
    +
    +http.createServer(function (request, response) {
    +  response.writeHead(200, {'Content-Type': 'text/plain'});
    +  response.end('Hello World\n');
    +}).listen(8124);
    +
    +sys.puts('Server running at http://127.0.0.1:8124/');
    +
    + +

    To run the server, put the code into a file called example.js and execute +it with the node program

    + +
    > node example.js
    +Server running at http://127.0.0.1:8124/
    +
    + +

    All of the examples in the documentation can be run similarly.

    + +

    Standard Modules

    + +

    Node comes with a number of modules that are compiled in to the process, +most of which are documented below. The most common way to use these modules +is with require('name') and then assigning the return value to a local +variable with the same name as the module.

    + +

    Example:

    + +
    var sys = require('sys');
    +
    + +

    It is possible to extend node with other modules. See 'Modules'

    + +

    Buffers

    + +

    Pure Javascript is Unicode friendly but not nice to binary data. When +dealing with TCP streams or the file system, it's necessary to handle octet +streams. Node has several strategies for manipulating, creating, and +consuming octet streams.

    + +

    Raw data is stored in instances of the Buffer class. A Buffer is similar +to an array of integers but corresponds to a raw memory allocation outside +the V8 heap. A Buffer cannot be resized. +Access the class with require('buffer').Buffer.

    + +

    Converting between Buffers and JavaScript string objects requires an explicit encoding +method. Node supports 3 string encodings: UTF-8 ('utf8'), ASCII ('ascii'), and +Binary ('binary').

    + +
      +
    • 'ascii' - for 7 bit ASCII data only. This encoding method is very fast, and will +strip the high bit if set.

    • +
    • 'binary' - for 8 bit binary data such as images.

    • +
    • 'utf8' - Unicode characters. Many web pages and other document formats use UTF-8.

    • +
    + + +

    new Buffer(size)

    + +

    Allocates a new buffer of size octets.

    + +

    new Buffer(array)

    + +

    Allocates a new buffer using an array of octets.

    + +

    new Buffer(str, encoding = 'utf8')

    + +

    Allocates a new buffer containing the given str.

    + +

    buffer.write(string, encoding, offset)

    + +

    Writes string to the buffer at offset using the given encoding. Returns +number of octets written. If buffer did not contain enough space to fit +the entire string it will write a partial amount of the string. In the case +of 'utf8' encoding, the method will not write partial characters.

    + +

    Example: write a utf8 string into a buffer, then print it

    + +
    var sys = require('sys'),
    +  Buffer = require('buffer').Buffer,
    +  buf = new Buffer(256),
    +  len;
    +
    +len = buf.write('\u00bd + \u00bc = \u00be', 'utf8', 0);
    +sys.puts(len + " bytes: " + buf.toString('utf8', 0, len));
    +
    +// 12 bytes: ½ + ¼ = ¾
    +
    + +

    buffer.toString(encoding, start, end)

    + +

    Decodes and returns a string from buffer data encoded with encoding +beginning at start and ending at end.

    + +

    See buffer.write() example, above.

    + +

    buffer[index]

    + +

    Get and set the octet at index. The values refer to individual bytes, +so the legal range is between 0x00 and 0xFF hex or 0 and 255.

    + +

    Example: copy an ASCII string into a buffer, one byte at a time:

    + +
    var sys = require('sys'),
    +  Buffer = require('buffer').Buffer,
    +  str = "node.js",
    +  buf = new Buffer(str.length),
    +  i;
    +
    +for (i = 0; i < str.length ; i += 1) {
    +  buf[i] = str.charCodeAt(i);
    +}
    +
    +sys.puts(buf);
    +
    +// node.js
    +
    + +

    Buffer.byteLength(string, encoding)

    + +

    Gives the actual byte length of a string. This is not the same as +String.prototype.length since that returns the number of characters in a +string.

    + +

    Example:

    + +
    var sys = require('sys'),
    +  Buffer = require('buffer').Buffer,
    +  str = '\u00bd + \u00bc = \u00be';
    +
    +sys.puts(str + ": " + str.length + " characters, " + 
    +  Buffer.byteLength(str, 'utf8') + " bytes");
    +
    +// ½ + ¼ = ¾: 9 characters, 12 bytes
    +
    + +

    buffer.length

    + +

    The size of the buffer in bytes. Note that this is not necessarily the size +of the contents. length refers to the amount of memory allocated for the +buffer object. It does not change when the contents of the buffer are changed.

    + +
    var sys = require('sys'),
    +  Buffer = require('buffer').Buffer,
    +  buf = new Buffer(1234);
    +
    +sys.puts(buf.length);
    +buf.write("some string", "ascii", 0);
    +sys.puts(buf.length);
    +
    +// 1234
    +// 1234
    +
    + +

    buffer.copy(targetBuffer, targetStart, sourceStart, sourceEnd)

    + +

    Does a memcpy() between buffers.

    + +

    Example: build two Buffers, then copy buf1 from byte 16 through byte 20 +into buf2, starting at the 8th byte in buf2.

    + +
    var sys = require('sys'),
    +  Buffer = require('buffer').Buffer,
    +  buf1 = new Buffer(26),
    +  buf2 = new Buffer(26),
    +  i;
    +
    +for (i = 0 ; i < 26 ; i += 1) {
    +  buf1[i] = i + 97; // 97 is ASCII a
    +  buf2[i] = 33; // ASCII !
    +}
    +
    +buf1.copy(buf2, 8, 16, 20);
    +sys.puts(buf2.toString('ascii', 0, 25));
    +
    +// !!!!!!!!qrst!!!!!!!!!!!!!
    +
    + +

    buffer.slice(start, end)

    + +

    Returns a new buffer which references the +same memory as the old, but offset and cropped by the start and end +indexes.

    + +

    Modifying the new buffer slice will modify memory in the original buffer!

    + +

    Example: build a Buffer with the ASCII alphabet, take a slice, then modify one byte +from the original Buffer.

    + +
    var sys = require('sys'),
    +  Buffer = require('buffer').Buffer,
    +  buf1 = new Buffer(26), buf2,
    +  i;
    +
    +for (i = 0 ; i < 26 ; i += 1) {
    +  buf1[i] = i + 97; // 97 is ASCII a
    +}
    +
    +buf2 = buf1.slice(0, 3);
    +sys.puts(buf2.toString('ascii', 0, buf2.length));
    +buf1[0] = 33;
    +sys.puts(buf2.toString('ascii', 0, buf2.length));
    +
    +// abc
    +// !bc
    +
    + +

    EventEmitter

    + +

    Many objects in Node emit events: a TCP server emits an event each time +there is a stream, a child process emits an event when it exits. All +objects which emit events are instances of events.EventEmitter.

    + +

    Events are represented by a camel-cased string. Here are some examples: +'stream', 'data', 'messageBegin'.

    + +

    Functions can be then be attached to objects, to be executed when an event +is emitted. These functions are called listeners.

    + +

    require('events').EventEmitter to access the EventEmitter class.

    + +

    All EventEmitters emit the event 'newListener' when new listeners are +added.

    + +

    When an EventEmitter experiences an error, the typical action is to emit an +'error' event. Error events are special--if there is no handler for them +they will print a stack trace and exit the program.

    + +

    Event: 'newListener'

    + +

    function (event, listener) { }

    + +

    This event is made any time someone adds a new listener.

    + +

    Event: 'error'

    + +

    function (exception) { }

    + +

    If an error was encountered, then this event is emitted. This event is +special - when there are no listeners to receive the error Node will +terminate execution and display the exception's stack trace.

    + +

    emitter.addListener(event, listener)

    + +

    Adds a listener to the end of the listeners array for the specified event.

    + +
    server.addListener('stream', function (stream) {
    +  sys.puts('someone connected!');
    +});
    +
    + +

    emitter.removeListener(event, listener)

    + +

    Remove a listener from the listener array for the specified event. +Caution: changes array indices in the listener array behind the listener.

    + +

    emitter.removeAllListeners(event)

    + +

    Removes all listeners from the listener array for the specified event.

    + +

    emitter.listeners(event)

    + +

    Returns an array of listeners for the specified event. This array can be +manipulated, e.g. to remove listeners.

    + +

    emitter.emit(event, arg1, arg2, ...)

    + +

    Execute each of the listeners in order with the supplied arguments.

    + +

    Streams

    + +

    A stream is an abstract interface implemented by various objects in Node. +For example a request to an HTTP server is a stream, as is stdout. Streams +are readable, writable, or both. All streams are instances of EventEmitter.

    + +

    Readable Stream

    + +

    A readable stream has the following methods, members, and events.

    + +

    Event: 'data'

    + +

    function (data) { }

    + +

    The 'data' event emits either a Buffer (by default) or a string if +setEncoding() was used.

    + +

    Event: 'end'

    + +

    function () { }

    + +

    Emitted when the stream has received an EOF (FIN in TCP terminology). +Indicates that no more 'data' events will happen. If the stream is also +writable, it may be possible to continue writing.

    + +

    Event: 'error'

    + +

    function (exception) { }

    + +

    Emitted if there was an error receiving data.

    + +

    Event: 'close'

    + +

    function () { }

    + +

    Emitted when the underlying file descriptor has be closed. Not all streams +will emit this. (For example, an incoming HTTP request will not emit +'close'.)

    + +

    stream.setEncoding(encoding)

    + +

    Makes the data event emit a string instead of a Buffer. encoding can be +'utf8', 'ascii', or 'binary'.

    + +

    stream.pause()

    + +

    Pauses the incoming 'data' events.

    + +

    stream.resume()

    + +

    Resumes the incoming 'data' events after a pause().

    + +

    stream.destroy()

    + +

    Closes the underlying file descriptor. Stream will not emit any more events.

    + +

    Writable Stream

    + +

    A writable stream has the following methods, members, and events.

    + +

    Event: 'drain'

    + +

    function () { }

    + +

    Emitted after a write() method was called that returned false to +indicate that it is safe to write again.

    + +

    Event: 'error'

    + +

    function (exception) { }

    + +

    Emitted on error with the exception exception.

    + +

    Event: 'close'

    + +

    function () { }

    + +

    Emitted when the underlying file descriptor has been closed.

    + +

    stream.write(string, encoding)

    + +

    Writes string with the given encoding to the stream. Returns true if +the string has been flushed to the kernel buffer. Returns false to +indicate that the kernel buffer is full, and the data will be sent out in +the future. The 'drain' event will indicate when the kernel buffer is +empty again. The encoding defaults to 'utf8'.

    + +

    stream.write(buffer)

    + +

    Same as the above except with a raw buffer.

    + +

    stream.end()

    + +

    Terminates the stream with EOF or FIN.

    + +

    stream.end(string, encoding)

    + +

    Sends string with the given encoding and terminates the stream with EOF +or FIN. This is useful to reduce the number of packets sent.

    + +

    stream.end(buffer)

    + +

    Same as above but with a buffer.

    + +

    stream.destroy()

    + +

    Closes the underlying file descriptor. Stream will not emit any more events.

    + +

    Global Objects

    + +

    These object are available in the global scope and can be accessed from anywhere.

    + +

    global

    + +

    The global namespace object.

    + +

    process

    + +

    The process object. Most stuff lives in here. See the 'process object' +section.

    + +

    require()

    + +

    To require modules. See the 'Modules' section.

    + +

    require.paths

    + +

    An array of search paths for require(). This array can be modified to add custom paths.

    + +

    Example: add a new path to the beginning of the search list

    + +
    var sys = require('sys');
    +
    +require.paths.unshift('/usr/local/node');
    +sys.puts(require.paths);
    +// /usr/local/node,/Users/mjr/.node_libraries
    +
    + +

    __filename

    + +

    The filename of the script being executed. This is the absolute path, and not necessarily +the same filename passed in as a command line argument.

    + +

    __dirname

    + +

    The dirname of the script being executed.

    + +

    Example: running node example.js from /Users/mjr

    + +
    var sys = require('sys');
    +sys.puts(__filename);
    +sys.puts(__dirname);
    +// /Users/mjr/example.js
    +// /Users/mjr
    +
    + +

    module

    + +

    A reference to the current module (of type process.Module). In particular +module.exports is the same as the exports object. See src/process.js +for more information.

    + +

    process

    + +

    The process object is a global object and can be accessed from anywhere. +It is an instance of EventEmitter.

    + +

    Event: 'exit'

    + +

    function () {}

    + +

    Emitted when the process is about to exit. This is a good hook to perform +constant time checks of the module's state (like for unit tests). The main +event loop will no longer be run after the 'exit' callback finishes, so +timers may not be scheduled.

    + +

    Example of listening for exit:

    + +
    var sys = require('sys');
    +
    +process.addListener('exit', function () {
    +  process.nextTick(function () {
    +   sys.puts('This will not run');
    +  });
    +  sys.puts('About to exit.');
    +});
    +
    + +

    Event: 'uncaughtException'

    + +

    function (err) { }

    + +

    Emitted when an exception bubbles all the way back to the event loop. If a +listener is added for this exception, the default action (which is to print +a stack trace and exit) will not occur.

    + +

    Example of listening for uncaughtException:

    + +
    var sys = require('sys');
    +
    +process.addListener('uncaughtException', function (err) {
    +  sys.puts('Caught exception: ' + err);
    +});
    +
    +setTimeout(function () {
    +  sys.puts('This will still run.');
    +}, 500);
    +
    +// Intentionally cause an exception, but don't catch it.
    +nonexistentFunc();
    +sys.puts('This will not run.');
    +
    + +

    Note that uncaughtException is a very crude mechanism for exception +handling. Using try / catch in your program will give you more control over +your program's flow. Especially for server programs that are designed to +stay running forever, uncaughtException can be a useful safety mechanism.

    + +

    Signal Events

    + +

    function () {}

    + +

    Emitted when the processes receives a signal. See sigaction(2) for a list of +standard POSIX signal names such as SIGINT, SIGUSR1, etc.

    + +

    Example of listening for SIGINT:

    + +
    var sys = require('sys'),
    +    stdin = process.openStdin();
    +
    +process.addListener('SIGINT', function () {
    +  sys.puts('Got SIGINT.  Press Control-D to exit.');
    +});
    +
    + +

    An easy way to send the SIGINT signal is with Control-C in most terminal +programs.

    + +

    process.stdout

    + +

    A writable stream to stdout.

    + +

    Example: the definition of sys.puts

    + +
    exports.puts = function (d) {
    +  process.stdout.write(d + '\n');
    +};
    +
    + +

    process.openStdin()

    + +

    Opens the standard input stream, returns a readable stream.

    + +

    Example of opening standard input and listening for both events:

    + +
    var stdin = process.openStdin();
    +
    +stdin.setEncoding('utf8');
    +
    +stdin.addListener('data', function (chunk) {
    +  process.stdout.write('data: ' + chunk);
    +});
    +
    +stdin.addListener('end', function () {
    +  process.stdout.write('end');
    +});
    +
    + +

    process.argv

    + +

    An array containing the command line arguments. The first element will be +'node', the second element will be the name of the JavaScript file. The +next elements will be any additional command line arguments.

    + +
    // print process.argv
    +var sys = require('sys');
    +
    +process.argv.forEach(function (val, index, array) {
    +  sys.puts(index + ': ' + val);
    +});
    +
    + +

    This will generate:

    + +
    $ node process-2.js one two=three four
    +0: node
    +1: /Users/mjr/work/node/process-2.js
    +2: one
    +3: two=three
    +4: four
    +
    + +

    process.chdir(directory)

    + +

    Changes the current working directory of the process or throws an exception if that fails.

    + +
    var sys = require('sys');
    +
    +sys.puts('Starting directory: ' + process.cwd());
    +try {
    +  process.chdir('/tmp');
    +  sys.puts('New directory: ' + process.cwd());
    +}
    +catch (err) {
    +  sys.puts('chdir: ' + err);
    +}
    +
    + +

    process.compile(code, filename)

    + +

    Similar to eval except that you can specify a filename for better +error reporting and the code cannot see the local scope. The value of filename +will be used as a filename if a stack trace is generated by the compiled code.

    + +

    Example of using process.compile and eval to run the same code:

    + +
    var sys = require('sys'),
    +    localVar = 123,
    +    compiled, evaled;
    +
    +compiled = process.compile('localVar = 1;', 'myfile.js');
    +sys.puts('localVar: ' + localVar + ', compiled: ' + compiled);
    +evaled = eval('localVar = 1;');
    +sys.puts('localVar: ' + localVar + ', evaled: ' + evaled);
    +
    +// localVar: 123, compiled: 1
    +// localVar: 1, evaled: 1
    +
    + +

    process.compile does not have access to the local scope, so localVar is unchanged. +eval does have access to the local scope, so localVar is changed.

    + +

    In case of syntax error in code, process.compile exits node.

    + +

    See also: Script

    + +

    process.cwd()

    + +

    Returns the current working directory of the process.

    + +
    require('sys').puts('Current directory: ' + process.cwd());
    +
    + +

    process.env

    + +

    An object containing the user environment. See environ(7).

    + +

    process.exit(code)

    + +

    Ends the process with the specified code. If omitted, exit uses the +'success' code 0.

    + +

    To exit with a 'failure' code:

    + +
    process.exit(1);
    +
    + +

    The shell that executed node should see the exit code as 1.

    + +

    process.getgid(), process.setgid(id)

    + +

    Gets/sets the group identity of the process. (See setgid(2).) This is the numerical group id, not the group name.

    + +
    var sys = require('sys');
    +
    +sys.puts('Current gid: ' + process.getgid());
    +try {
    +  process.setgid(501);
    +  sys.puts('New gid: ' + process.getgid());
    +}
    +catch (err) {
    +  sys.puts('Failed to set gid: ' + err);
    +}
    +
    + +

    process.getuid(), process.setuid(id)

    + +

    Gets/sets the user identity of the process. (See setuid(2).) This is the numerical userid, not the username.

    + +
    var sys = require('sys');
    +
    +sys.puts('Current uid: ' + process.getuid());
    +try {
    +  process.setuid(501);
    +  sys.puts('New uid: ' + process.getuid());
    +}
    +catch (err) {
    +  sys.puts('Failed to set uid: ' + err);
    +}
    +
    + +

    process.version

    + +

    A compiled-in property that exposes NODE_VERSION.

    + +
    require('sys').puts('Version: ' + process.version);
    +
    + +

    process.installPrefix

    + +

    A compiled-in property that exposes NODE_PREFIX.

    + +
    require('sys').puts('Prefix: ' + process.installPrefix);
    +
    + +

    process.kill(pid, signal)

    + +

    Send a signal to a process. pid is the process id and signal is the +string describing the signal to send. Signal names are strings like +'SIGINT' or 'SIGUSR1'. If omitted, the signal will be 'SIGINT'. +See kill(2) for more information.

    + +

    Note that just because the name of this function is process.kill, it is +really just a signal sender, like the kill system call. The signal sent +may do something other than kill the target process.

    + +

    Example of sending a signal to yourself:

    + +
    var sys = require('sys');
    +
    +process.addListener('SIGHUP', function () {
    +  sys.puts('Got SIGHUP signal.');
    +});
    +
    +setTimeout(function () {
    +  sys.puts('Exiting.');
    +  process.exit(0);
    +}, 100);
    +
    +process.kill(process.pid, 'SIGHUP');
    +
    + +

    process.pid

    + +

    The PID of the process.

    + +
    require('sys').puts('This process is pid ' + process.pid);
    +
    + +

    process.platform

    + +

    What platform you're running on. 'linux2', 'darwin', etc.

    + +
    require('sys').puts('This platform is ' + process.platform);
    +
    + +

    process.memoryUsage()

    + +

    Returns an object describing the memory usage of the Node process.

    + +
    var sys = require('sys');
    +
    +sys.puts(sys.inspect(process.memoryUsage()));
    +
    + +

    This will generate:

    + +
    { rss: 4935680
    +, vsize: 41893888
    +, heapTotal: 1826816
    +, heapUsed: 650472
    +}
    +
    + +

    heapTotal and heapUsed refer to V8's memory usage.

    + +

    process.nextTick(callback)

    + +

    On the next loop around the event loop call this callback. +This is not a simple alias to setTimeout(fn, 0), it's much more +efficient.

    + +
    var sys = require('sys');
    +
    +process.nextTick(function () {
    +  sys.puts('nextTick callback');
    +});
    +
    + +

    process.umask(mask)

    + +

    Sets or read the process's file mode creation mask. Child processes inherit +the mask from the parent process. Returns the old mask if mask argument is +given, otherwise returns the current mask.

    + +
    var sys = require('sys'),
    +    oldmask, newmask = 0644;
    +
    +oldmask = process.umask(newmask);
    +sys.puts('Changed umask from: ' + oldmask.toString(8) +
    +         ' to ' + newmask.toString(8));
    +
    + +

    sys

    + +

    These functions are in the module 'sys'. Use require('sys') to access +them.

    + +

    sys.puts(string)

    + +

    Outputs string and a trailing newline to stdout.

    + +
    require('sys').puts('String with a newline');
    +
    + +

    sys.print(string)

    + +

    Like puts() but without the trailing newline.

    + +
    require('sys').print('String with no newline');
    +
    + +

    sys.debug(string)

    + +

    A synchronous output function. Will block the process and +output string immediately to stderr.

    + +
    require('sys').debug('message on stderr');
    +
    + +

    sys.log(string)

    + +

    Output with timestamp on stdout.

    + +
    require('sys').log('Timestmaped message.');
    +
    + +

    sys.inspect(object, showHidden, depth)

    + +

    Return a string representation of object, which is useful for debugging.

    + +

    If showHidden is true, then the object's non-enumerable properties will be +shown too.

    + +

    If depth is provided, it tells inspect how many times to recurse while +formatting the object. This is useful for inspecting large complicated objects.

    + +

    The default is to only recurse twice. To make it recurse indefinitely, pass +in null for depth.

    + +

    Example of inspecting all properties of the sys object:

    + +
    var sys = require('sys');
    +
    +sys.puts(sys.inspect(sys, true, null));
    +
    + +

    Timers

    + +

    setTimeout(callback, delay, [arg, ...])

    + +

    To schedule execution of callback after delay milliseconds. Returns a +timeoutId for possible use with clearTimeout().

    + +

    clearTimeout(timeoutId)

    + +

    Prevents a timeout from triggering.

    + +

    setInterval(callback, delay, [arg, ...])

    + +

    To schedule the repeated execution of callback every delay milliseconds. +Returns a intervalId for possible use with clearInterval().

    + +

    Optionally, you can also pass arguments to the callback.

    + +

    clearInterval(intervalId)

    + +

    Stops a interval from triggering.

    + +

    Child Processes

    + +

    Node provides a tri-directional popen(3) facility through the ChildProcess +class.

    + +

    It is possible to stream data through the child's stdin, stdout, and +stderr in a fully non-blocking way.

    + +

    To create a child process use require('child_process').spawn().

    + +

    Child processes always have three streams associated with them. child.stdin, +child.stdout, and child.stderr.

    + +

    ChildProcess is an EventEmitter.

    + +

    Event: 'exit'

    + +

    function (code, signal) {}

    + +

    This event is emitted after the child process ends. If the process terminated +normally, code is the final exit code of the process, otherwise null. If +the process terminated due to receipt of a signal, signal is the string name +of the signal, otherwise null.

    + +

    After this event is emitted, the 'output' and 'error' callbacks will no +longer be made.

    + +

    See waitpid(2).

    + +

    child_process.spawn(command, args, env)

    + +

    Launches a new process with the given command, command line arguments, and +environment variables. If omitted, args defaults to an empty Array, and env +defaults to process.env.

    + +

    Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:

    + +
    var sys   = require('sys'),
    +    spawn = require('child_process').spawn,
    +    ls    = spawn('ls', ['-lh', '/usr']);
    +
    +ls.stdout.addListener('data', function (data) {
    +  sys.print('stdout: ' + data);
    +});
    +
    +ls.stderr.addListener('data', function (data) {
    +  sys.print('stderr: ' + data);
    +});
    +
    +ls.addListener('exit', function (code) {
    +  sys.puts('child process exited with code ' + code);
    +});
    +
    + +

    Example of checking for failed exec:

    + +
    var sys   = require('sys'),
    +    spawn = require('child_process').spawn,
    +    child = spawn('bad_command');
    +
    +child.stderr.addListener('data', function (data) {
    +  if (/^execvp\(\)/.test(data.asciiSlice(0,data.length))) {
    +    sys.puts('Failed to start child process.');
    +  }
    +});
    +
    + +

    See also: child_process.exec()

    + +

    child.kill(signal)

    + +

    Send a signal to the child process. If no argument is given, the process will +be sent 'SIGTERM'. See signal(7) for a list of available signals.

    + +
    var sys   = require('sys'),
    +    spawn = require('child_process').spawn,
    +    grep  = spawn('grep', ['ssh']);
    +
    +grep.addListener('exit', function (code, signal) {
    +  sys.puts('child process terminated due to receipt of signal '+signal);
    +});
    +
    +// send SIGHUP to process
    +grep.kill('SIGHUP');
    +
    + +

    Note that while the function is called kill, the signal delivered to the child +process may not actually kill it. kill really just sends a signal to a process.

    + +

    See kill(2)

    + +

    child.pid

    + +

    The PID of the child process.

    + +

    Example:

    + +
    var sys   = require('sys'),
    +    spawn = require('child_process').spawn,
    +    grep  = spawn('grep', ['ssh']);
    +
    +sys.puts('Spawned child pid: ' + grep.pid);
    +grep.stdin.end();
    +
    + +

    child.stdin.write(data, encoding)

    + +

    Write data to the child process's stdin. The second argument is optional and +specifies the encoding: possible values are 'utf8', 'ascii', and +'binary'.

    + +

    Example: A very elaborate way to run 'ps ax | grep ssh'

    + +
    var sys   = require('sys'),
    +    spawn = require('child_process').spawn,
    +    ps    = spawn('ps', ['ax']),
    +    grep  = spawn('grep', ['ssh']);
    +
    +ps.stdout.addListener('data', function (data) {
    +  grep.stdin.write(data);
    +});
    +
    +ps.stderr.addListener('data', function (data) {
    +  sys.print('ps stderr: ' + data);
    +});
    +
    +ps.addListener('exit', function (code) {
    +  if (code !== 0) {
    +    sys.puts('ps process exited with code ' + code);
    +  }
    +  grep.stdin.end();
    +});
    +
    +grep.stdout.addListener('data', function (data) {
    +  sys.print(data);
    +});
    +
    +grep.stderr.addListener('data', function (data) {
    +  sys.print('grep stderr: ' + data);
    +});
    +
    +grep.addListener('exit', function (code) {
    +  if (code !== 0) {
    +    sys.puts('grep process exited with code ' + code);
    +  }
    +});
    +
    + +

    child.stdin.end()

    + +

    Closes the child process's stdin stream. This often causes the child process to terminate.

    + +

    Example:

    + +
    var sys   = require('sys'),
    +    spawn = require('child_process').spawn,
    +    grep  = spawn('grep', ['ssh']);
    +
    +grep.addListener('exit', function (code) {
    +  sys.puts('child process exited with code ' + code);
    +});
    +
    +grep.stdin.end();
    +
    + +

    child_process.exec(command, [options, ] callback)

    + +

    High-level way to execute a command as a child process, buffer the +output, and return it all in a callback.

    + +
    var sys   = require('sys'),
    +    exec  = require('child_process').exec,
    +    child;
    +
    +child = exec('cat *.js bad_file | wc -l', 
    +  function (error, stdout, stderr) {
    +    sys.print('stdout: ' + stdout);
    +    sys.print('stderr: ' + stderr);
    +    if (error !== null) {
    +      sys.puts('exec error: ' + error);
    +    }
    +  });
    +
    + +

    The callback gets the arguments (error, stdout, stderr). On success, error +will be null. On error, error will be an instance of Error and err.code +will be the exit code of the child process, and err.signal will be set to the +signal that terminated the process.

    + +

    There is a second optional argument to specify several options. The default options are

    + +
    { encoding: 'utf8'
    +, timeout: 0
    +, maxBuffer: 200*1024
    +, killSignal: 'SIGKILL'
    +}
    +
    + +

    If timeout is greater than 0, then it will kill the child process +if it runs longer than timeout milliseconds. The child process is killed with +killSignal (default: 'SIGKILL'). maxBuffer specifies the largest +amount of data allowed on stdout or stderr - if this value is exceeded then +the child process is killed.

    + +

    Script

    + +

    Script class compiles and runs JavaScript code. You can access this class with:

    + +
    var Script = process.binding('evals').Script;
    +
    + +

    New JavaScript code can be compiled and run immediately or compiled, saved, and run later.

    + +

    Script.runInThisContext(code, filename)

    + +

    Similar to process.compile. Script.runInThisContext compiles code as if it were loaded from filename, +runs it and returns the result. Running code does not have access to local scope. filename is optional.

    + +

    Example of using Script.runInThisContext and eval to run the same code:

    + +
    var sys = require('sys'),
    +    localVar = 123,
    +    usingscript, evaled,
    +    Script = process.binding('evals').Script;
    +
    +usingscript = Script.runInThisContext('localVar = 1;',
    +  'myfile.js');
    +sys.puts('localVar: ' + localVar + ', usingscript: ' +
    +  usingscript);
    +evaled = eval('localVar = 1;');
    +sys.puts('localVar: ' + localVar + ', evaled: ' +
    +  evaled);
    +
    +// localVar: 123, usingscript: 1
    +// localVar: 1, evaled: 1
    +
    + +

    Script.runInThisContext does not have access to the local scope, so localVar is unchanged. +eval does have access to the local scope, so localVar is changed.

    + +

    In case of syntax error in code, Script.runInThisContext emits the syntax error to stderr +and throws.an exception.

    + +

    Script.runInNewContext(code, sandbox, filename)

    + +

    Script.runInNewContext compiles code to run in sandbox as if it were loaded from filename, +then runs it and returns the result. Running code does not have access to local scope and +the object sandbox will be used as the global object for code. +sandbox and filename are optional.

    + +

    Example: compile and execute code that increments a global variable and sets a new one. +These globals are contained in the sandbox.

    + +
    var sys = require('sys'),
    +    Script = process.binding('evals').Script,
    +    sandbox = {
    +      animal: 'cat',
    +      count: 2
    +    };
    +
    +Script.runInNewContext(
    +  'count += 1; name = "kitty"', sandbox, 'myfile.js');
    +sys.puts(sys.inspect(sandbox));
    +
    +// { animal: 'cat', count: 3, name: 'kitty' }
    +
    + +

    Note that running untrusted code is a tricky business requiring great care. To prevent accidental +global variable leakage, Script.runInNewContext is quite useful, but safely running untrusted code +requires a separate process.

    + +

    In case of syntax error in code, Script.runInThisContext emits the syntax error to stderr +and throws an exception.

    + +

    new Script(code, filename)

    + +

    new Script compiles code as if it were loaded from filename, +but does not run it. Instead, it returns a Script object representing this compiled code. +This script can be run later many times using methods below. +The returned script is not bound to any global object. +It is bound before each run, just for that run. filename is optional.

    + +

    In case of syntax error in code, new Script emits the syntax error to stderr +and throws an exception.

    + +

    script.runInThisContext()

    + +

    Similar to Script.runInThisContext (note capital 'S'), but now being a method of a precompiled Script object. +script.runInThisContext runs the code of script and returns the result. +Running code does not have access to local scope, but does have access to the global object +(v8: in actual context).

    + +

    Example of using script.runInThisContext to compile code once and run it multiple times:

    + +
    var sys = require('sys'),
    +    Script = process.binding('evals').Script,
    +    scriptObj, i;
    +
    +globalVar = 0;
    +
    +scriptObj = new Script('globalVar += 1', 'myfile.js');
    +
    +for (i = 0; i < 1000 ; i += 1) {
    +  scriptObj.runInThisContext();
    +}
    +
    +sys.puts(globalVar);
    +
    +// 1000
    +
    + +

    script.runInNewContext(sandbox)

    + +

    Similar to Script.runInNewContext (note capital 'S'), but now being a method of a precompiled Script object. +script.runInNewContext runs the code of script with sandbox as the global object and returns the result. +Running code does not have access to local scope. sandbox is optional.

    + +

    Example: compile code that increments a global variable and sets one, then execute this code multiple times. +These globals are contained in the sandbox.

    + +
    var sys = require('sys'),
    +    Script = process.binding('evals').Script,
    +    scriptObj, i,
    +    sandbox = {
    +      animal: 'cat',
    +      count: 2
    +    };
    +
    +scriptObj = new Script(
    +    'count += 1; name = "kitty"', 'myfile.js');
    +
    +for (i = 0; i < 10 ; i += 1) {
    +  scriptObj.runInNewContext(sandbox);
    +}
    +
    +sys.puts(sys.inspect(sandbox));
    +
    +// { animal: 'cat', count: 12, name: 'kitty' }
    +
    + +

    Note that running untrusted code is a tricky business requiring great care. To prevent accidental +global variable leakage, script.runInNewContext is quite useful, but safely running untrusted code +requires a separate process.

    + +

    File System

    + +

    File I/O is provided by simple wrappers around standard POSIX functions. To +use this module do require('fs'). All the methods have asynchronous and +synchronous forms.

    + +

    The asynchronous form always take a completion callback as its last argument. +The arguments passed to the completion callback depend on the method, but the +first argument is always reserved for an exception. If the operation was +completed successfully, then the first argument will be null or undefined.

    + +

    Here is an example of the asynchronous version:

    + +
    var fs = require('fs'),
    +    sys = require('sys');
    +
    +fs.unlink('/tmp/hello', function (err) {
    +  if (err) throw err;
    +  sys.puts('successfully deleted /tmp/hello');
    +});
    +
    + +

    Here is the synchronous version:

    + +
    var fs = require('fs'),
    +    sys = require('sys');
    +
    +fs.unlinkSync('/tmp/hello')
    +sys.puts('successfully deleted /tmp/hello');
    +
    + +

    With the asynchronous methods there is no guaranteed ordering. So the +following is prone to error:

    + +
    fs.rename('/tmp/hello', '/tmp/world', function (err) {
    +  if (err) throw err;
    +  sys.puts('renamed complete');
    +});
    +fs.stat('/tmp/world', function (err, stats) {
    +  if (err) throw err;
    +  sys.puts('stats: ' + JSON.stringify(stats));
    +});
    +
    + +

    It could be that fs.stat is executed before fs.rename. +The correct way to do this is to chain the callbacks.

    + +
    fs.rename('/tmp/hello', '/tmp/world', function (err) {
    +  if (err) throw err;
    +  fs.stat('/tmp/world', function (err, stats) {
    +    if (err) throw err;
    +    sys.puts('stats: ' + JSON.stringify(stats));
    +  });
    +});
    +
    + +

    In busy processes, the programmer is strongly encouraged to use the +asynchronous versions of these calls. The synchronous versions will block +the entire process until they complete--halting all connections.

    + +

    fs.rename(path1, path2, callback)

    + +

    Asynchronous rename(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.renameSync(path1, path2)

    + +

    Synchronous rename(2).

    + +

    fs.truncate(fd, len, callback)

    + +

    Asynchronous ftruncate(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.truncateSync(fd, len)

    + +

    Synchronous ftruncate(2).

    + +

    fs.chmod(path, mode, callback)

    + +

    Asynchronous chmod(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.chmodSync(path, mode)

    + +

    Synchronous chmod(2).

    + +

    fs.stat(path, callback), fs.lstat(path, callback), fs.fstat(fd, callback)

    + +

    Asynchronous stat(2), lstat(2) or fstat(2). The callback gets two arguments (err, stats) where stats is a fs.Stats object. It looks like this:

    + +
    { dev: 2049
    +, ino: 305352
    +, mode: 16877
    +, nlink: 12
    +, uid: 1000
    +, gid: 1000
    +, rdev: 0
    +, size: 4096
    +, blksize: 4096
    +, blocks: 8
    +, atime: '2009-06-29T11:11:55Z'
    +, mtime: '2009-06-29T11:11:40Z'
    +, ctime: '2009-06-29T11:11:40Z' 
    +}
    +
    + +

    See the fs.Stats section below for more information.

    + +

    fs.statSync(path), fs.lstatSync(path), fs.fstatSync(fd)

    + +

    Synchronous stat(2), lstat(2) or fstat(2). Returns an instance of fs.Stats.

    + +

    fs.link(srcpath, dstpath, callback)

    + +

    Asynchronous link(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.linkSync(dstpath, srcpath)

    + +

    Synchronous link(2).

    + +

    fs.symlink(linkdata, path, callback)

    + +

    Asynchronous symlink(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.symlinkSync(linkdata, path)

    + +

    Synchronous symlink(2).

    + +

    fs.readlink(path, callback)

    + +

    Asynchronous readlink(2). The callback gets two arguments (err, resolvedPath).

    + +

    fs.readlinkSync(path)

    + +

    Synchronous readlink(2). Returns the resolved path.

    + +

    fs.realpath(path, callback)

    + +

    Asynchronous realpath(2). The callback gets two arguments (err, resolvedPath).

    + +

    fs.realpathSync(path)

    + +

    Synchronous realpath(2). Returns the resolved path.

    + +

    fs.unlink(path, callback)

    + +

    Asynchronous unlink(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.unlinkSync(path)

    + +

    Synchronous unlink(2).

    + +

    fs.rmdir(path, callback)

    + +

    Asynchronous rmdir(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.rmdirSync(path)

    + +

    Synchronous rmdir(2).

    + +

    fs.mkdir(path, mode, callback)

    + +

    Asynchronous mkdir(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.mkdirSync(path, mode)

    + +

    Synchronous mkdir(2).

    + +

    fs.readdir(path, callback)

    + +

    Asynchronous readdir(3). Reads the contents of a directory. +The callback gets two arguments (err, files) where files is an array of +the names of the files in the directory excluding '.' and '..'.

    + +

    fs.readdirSync(path)

    + +

    Synchronous readdir(3). Returns an array of filenames excluding '.' and +'..'.

    + +

    fs.close(fd, callback)

    + +

    Asynchronous close(2). No arguments other than a possible exception are given to the completion callback.

    + +

    fs.closeSync(fd)

    + +

    Synchronous close(2).

    + +

    fs.open(path, flags, mode, callback)

    + +

    Asynchronous file open. See open(2). Flags can be 'r', 'r+', 'w', 'w+', 'a', +or 'a+'. The callback gets two arguments (err, fd).

    + +

    fs.openSync(path, flags, mode)

    + +

    Synchronous open(2).

    + +

    fs.write(fd, buffer, offset, length, position, callback)

    + +

    Write buffer to the file specified by fd.

    + +

    offset and length determine the part of the buffer to be written.

    + +

    position refers to the offset from the beginning of the file where this data +should be written. If position is null, the data will be written at the +current position. +See pwrite(2).

    + +

    The callback will be given two arguments (err, written) where written +specifies how many bytes were written.

    + +

    fs.writeSync(fd, data, position, encoding)

    + +

    Synchronous version of fs.write(). Returns the number of bytes written.

    + +

    fs.read(fd, buffer, offset, length, position, callback)

    + +

    Read data from the file specified by fd.

    + +

    buffer is the buffer that the data will be written to.

    + +

    offset is offset within the buffer where writing will start.

    + +

    length is an integer specifying the number of bytes to read.

    + +

    position is an integer specifying where to begin reading from in the file. +If position is null, data will be read from the current file position.

    + +

    The callback is given the two arguments, (err, bytesRead).

    + +

    fs.readSync(fd, buffer, offset, length, position)

    + +

    Synchronous version of fs.read. Returns the number of bytesRead.

    + +

    fs.readFile(filename, [encoding,] callback)

    + +

    Asynchronously reads the entire contents of a file. Example:

    + +
    fs.readFile('/etc/passwd', function (err, data) {
    +  if (err) throw err;
    +  sys.puts(data);
    +});
    +
    + +

    The callback is passed two arguments (err, data), where data is the +contents of the file.

    + +

    If no encoding is specified, then the raw buffer is returned.

    + +

    fs.readFileSync(filename [, encoding])

    + +

    Synchronous version of fs.readFile. Returns the contents of the filename.

    + +

    If encoding is specified then this function returns a string. Otherwise it +returns a buffer.

    + +

    fs.writeFile(filename, data, encoding='utf8', callback)

    + +

    Asynchronously writes data to a file. Example:

    + +
    fs.writeFile('message.txt', 'Hello Node', function (err) {
    +  if (err) throw err;
    +  sys.puts('It\'s saved!');
    +});
    +
    + +

    fs.writeFileSync(filename, data, encoding='utf8')

    + +

    The synchronous version of fs.writeFile.

    + +

    fs.watchFile(filename, [options,] listener)

    + +

    Watch for changes on filename. The callback listener will be called each +time the file changes.

    + +

    The second argument is optional. The options if provided should be an object +containing two members a boolean, persistent, and interval, a polling +value in milliseconds. The default is {persistent: true, interval: 0}.

    + +

    The listener gets two arguments the current stat object and the previous +stat object:

    + +
    fs.watchFile(f, function (curr, prev) {
    +  sys.puts('the current mtime is: ' + curr.mtime);
    +  sys.puts('the previous mtime was: ' + prev.mtime);
    +});
    +
    + +

    These stat objects are instances of fs.Stat.

    + +

    fs.unwatchFile(filename)

    + +

    Stop watching for changes on filename.

    + +

    fs.Stats

    + +

    Objects returned from fs.stat() and fs.lstat() are of this type.

    + +
      +
    • stats.isFile()
    • +
    • stats.isDirectory()
    • +
    • stats.isBlockDevice()
    • +
    • stats.isCharacterDevice()
    • +
    • stats.isSymbolicLink() (only valid with fs.lstat())
    • +
    • stats.isFIFO()
    • +
    • stats.isSocket()
    • +
    + + +

    fs.ReadStream

    + +

    ReadStream is a readable stream.

    + +

    fs.createReadStream(path, [options])

    + +

    Returns a new ReadStream object.

    + +

    options is an object with the following defaults:

    + +
    { 'flags': 'r'
    +, 'encoding': 'binary'
    +, 'mode': 0666
    +, 'bufferSize': 4 * 1024
    +}
    +
    + +

    readStream.readable

    + +

    A boolean that is true by default, but turns false after an 'error' +occured, the stream came to an 'end', or destroy() was called.

    + +

    readStream.pause()

    + +

    Stops the stream from reading further data. No 'data' event will be fired +until the stream is resumed.

    + +

    readStream.resume()

    + +

    Resumes the stream. Together with pause() this useful to throttle reading.

    + +

    readStream.destroy()

    + +

    Allows to close the stream before the 'end' is reached. No more events other +than 'close' will be fired after this method has been called.

    + +

    fs.WriteStream

    + +

    WriteStream is a writable stream.

    + +

    fs.createWriteStream(path, [options])

    + +

    Returns a new WriteStream object. +options is an object with the following defaults:

    + +
    { 'flags': 'w'
    +, 'encoding': 'binary'
    +, 'mode': 0666
    +}
    +
    + +

    writeStream.writeable

    + +

    A boolean that is true by default, but turns false after an 'error' +occurred or end() / destroy() was called.

    + +

    writeStream.write(data, encoding='utf8')

    + +

    Returns true if the data was flushed to the kernel, and false if it was +queued up for being written later. A 'drain' will fire after all queued data +has been written.

    + +

    The second optional parameter specifies the encoding of for the string.

    + +

    writeStream.end()

    + +

    Closes the stream right after all queued write() calls have finished.

    + +

    writeStream.destroy()

    + +

    Allows to close the stream regardless of its current state.

    + +

    HTTP

    + +

    To use the HTTP server and client one must require('http').

    + +

    The HTTP interfaces in Node are designed to support many features +of the protocol which have been traditionally difficult to use. +In particular, large, possibly chunk-encoded, messages. The interface is +careful to never buffer entire requests or responses--the +user is able to stream data.

    + +

    HTTP message headers are represented by an object like this:

    + +
    { 'content-length': '123'
    +, 'content-type': 'text/plain'
    +, 'stream': 'keep-alive'
    +, 'accept': '*/*'
    +}
    +
    + +

    Keys are lowercased. Values are not modified.

    + +

    In order to support the full spectrum of possible HTTP applications, Node's +HTTP API is very low-level. It deals with stream handling and message +parsing only. It parses a message into headers and body but it does not +parse the actual headers or the body.

    + +

    HTTPS is supported if OpenSSL is available on the underlying platform.

    + +

    http.Server

    + +

    This is an EventEmitter with the following events:

    + +

    Event: 'request'

    + +

    function (request, response) { }

    + +

    request is an instance of http.ServerRequest and response is + an instance of http.ServerResponse

    + +

    Event: 'connection'

    + +

    function (stream) { }

    + +

    When a new TCP stream is established. stream is an object of type + net.Stream. Usually users will not want to access this event. The + stream can also be accessed at request.connection.

    + +

    Event: 'close'

    + +

    function (errno) { }

    + +

    Emitted when the server closes.

    + +

    http.createServer(requestListener, [options])

    + +

    Returns a new web server object.

    + +

    The options argument is optional. The +options argument accepts the same values as the +options argument for net.Server.

    + +

    The requestListener is a function which is automatically +added to the 'request' event.

    + +

    Event: 'request'

    + +

    function (request, response) {}

    + +

    Emitted each time there is request. Note that there may be multiple requests +per connection (in the case of keep-alive connections).

    + +

    Event: 'upgrade'

    + +

    function (request, socket, head)

    + +

    Emitted each time a client requests a http upgrade. If this event isn't +listened for, then clients requesting an upgrade will have their connections +closed.

    + +
      +
    • request is the arguments for the http request, as it is in the request event.
    • +
    • socket is the network socket between the server and client.
    • +
    • head is an instance of Buffer, the first packet of the upgraded stream, this may be empty.
    • +
    + + +

    After this event is emitted, the request's socket will not have a data +event listener, meaning you will need to bind to it in order to handle data +sent to the server on that socket.

    + +

    Event: 'clientError'

    + +

    function (exception) {}

    + +

    If a client connection emits an 'error' event - it will forwarded here.

    + +

    server.listen(port, hostname=null, callback=null)

    + +

    Begin accepting connections on the specified port and hostname. If the +hostname is omitted, the server will accept connections directed to any +IPv4 address (INADDR_ANY).

    + +

    To listen to a unix socket, supply a filename instead of port and hostname.

    + +

    This function is asynchronous. The last parameter callback will be called +when the server has been bound to the port.

    + +

    server.listen(path, callback=null)

    + +

    Start a UNIX socket server listening for connections on the given path.

    + +

    This function is asynchronous. The last parameter callback will be called +when the server has been bound.

    + +

    server.setSecure(credentials)

    + +

    Enables HTTPS support for the server, with the crypto module credentials specifying the private key and certificate of the server, and optionally the CA certificates for use in client authentication.

    + +

    If the credentials hold one or more CA certificates, then the server will request for the client to submit a client certificate as part of the HTTPS connection handshake. The validity and content of this can be accessed via verifyPeer() and getPeerCertificate() from the server's request.connection.

    + +

    server.close()

    + +

    Stops the server from accepting new connections.

    + +

    http.ServerRequest

    + +

    This object is created internally by a HTTP server--not by +the user--and passed as the first argument to a 'request' listener.

    + +

    This is an EventEmitter with the following events:

    + +

    Event: 'data'

    + +

    function (chunk) { }

    + +

    Emitted when a piece of the message body is received.

    + +

    Example: A chunk of the body is given as the single +argument. The transfer-encoding has been decoded. The +body chunk is a string. The body encoding is set with +request.setBodyEncoding().

    + +

    Event: 'end'

    + +

    function () { }

    + +

    Emitted exactly once for each message. No arguments. After +emitted no other events will be emitted on the request.

    + +

    request.method

    + +

    The request method as a string. Read only. Example: +'GET', 'DELETE'.

    + +

    request.url

    + +

    Request URL string. This contains only the URL that is +present in the actual HTTP request. If the request is:

    + +
    GET /status?name=ryan HTTP/1.1\r\n
    +Accept: text/plain\r\n
    +\r\n
    +
    + +

    Then request.url will be:

    + +
    '/status?name=ryan'
    +
    + +

    If you would like to parse the URL into its parts, you can use +require('url').parse(request.url). Example:

    + +
    node> require('url').parse('/status?name=ryan')
    +{ href: '/status?name=ryan'
    +, search: '?name=ryan'
    +, query: 'name=ryan'
    +, pathname: '/status'
    +}
    +
    + +

    If you would like to extract the params from the query string, +you can use the require('querystring').parse function, or pass +true as the second argument to require('url').parse. Example:

    + +
    node> require('url').parse('/status?name=ryan', true)
    +{ href: '/status?name=ryan'
    +, search: '?name=ryan'
    +, query: { name: 'ryan' }
    +, pathname: '/status'
    +}
    +
    + +

    request.headers

    + +

    Read only.

    + +

    request.httpVersion

    + +

    The HTTP protocol version as a string. Read only. Examples: +'1.1', '1.0'. +Also request.httpVersionMajor is the first integer and +request.httpVersionMinor is the second.

    + +

    request.setEncoding(encoding='binary')

    + +

    Set the encoding for the request body. Either 'utf8' or 'binary'. Defaults +to 'binary'.

    + +

    request.pause()

    + +

    Pauses request from emitting events. Useful to throttle back an upload.

    + +

    request.resume()

    + +

    Resumes a paused request.

    + +

    request.connection

    + +

    The net.Stream object assocated with the connection.

    + +

    With HTTPS support, use request.connection.verifyPeer() and +request.connection.getPeerCertificate() to obtain the client's +authentication details.

    + +

    http.ServerResponse

    + +

    This object is created internally by a HTTP server--not by the user. It is +passed as the second parameter to the 'request' event. It is a writable stream.

    + +

    response.writeHead(statusCode[, reasonPhrase] , headers)

    + +

    Sends a response header to the request. The status code is a 3-digit HTTP +status code, like 404. The last argument, headers, are the response headers. +Optionally one can give a human-readable reasonPhrase as the second +argument.

    + +

    Example:

    + +
    var body = 'hello world';
    +response.writeHead(200, {
    +  'Content-Length': body.length,
    +  'Content-Type': 'text/plain'
    +});
    +
    + +

    This method must only be called once on a message and it must +be called before response.end() is called.

    + +

    response.write(chunk, encoding)

    + +

    This method must be called after writeHead was +called. It sends a chunk of the response body. This method may +be called multiple times to provide successive parts of the body.

    + +

    If chunk is a string, the second parameter +specifies how to encode it into a byte stream. By default the +encoding is 'ascii'.

    + +

    Note: This is the raw HTTP body and has nothing to do with +higher-level multi-part body encodings that may be used.

    + +

    The first time response.write() is called, it will send the buffered +header information and the first body to the client. The second time +response.write() is called, Node assumes you're going to be streaming +data, and sends that separately. That is, the response is buffered up to the +first chunk of body.

    + +

    response.end()

    + +

    This method signals to the server that all of the response headers and body +has been sent; that server should consider this message complete. +The method, response.end(), MUST be called on each +response.

    + +

    http.Client

    + +

    An HTTP client is constructed with a server address as its +argument, the returned handle is then used to issue one or more +requests. Depending on the server connected to, the client might +pipeline the requests or reestablish the stream after each +stream. Currently the implementation does not pipeline requests.

    + +

    Example of connecting to google.com:

    + +
    var sys = require('sys'),
    +   http = require('http');
    +var google = http.createClient(80, 'www.google.com');
    +var request = google.request('GET', '/',
    +  {'host': 'www.google.com'});
    +request.end();
    +request.addListener('response', function (response) {
    +  sys.puts('STATUS: ' + response.statusCode);
    +  sys.puts('HEADERS: ' + JSON.stringify(response.headers));
    +  response.setEncoding('utf8');
    +  response.addListener('data', function (chunk) {
    +    sys.puts('BODY: ' + chunk);
    +  });
    +});
    +
    + +

    http.createClient(port, host, secure, credentials)

    + +

    Constructs a new HTTP client. port and +host refer to the server to be connected to. A +stream is not established until a request is issued.

    + +

    secure is an optional boolean flag to enable https support and credentials is an optional credentials object from the crypto module, which may hold the client's private key, certificate, and a list of trusted CA certificates.

    + +

    If the connection is secure, but no explicit CA certificates are passed in the credentials, then node.js will default to the publicly trusted list of CA certificates, as given in http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt

    + +

    client.request([method], path, [request_headers])

    + +

    Issues a request; if necessary establishes stream. Returns a http.ClientRequest instance.

    + +

    method is optional and defaults to 'GET' if omitted.

    + +

    request_headers is optional. +Additional request headers might be added internally +by Node. Returns a ClientRequest object.

    + +

    Do remember to include the Content-Length header if you +plan on sending a body. If you plan on streaming the body, perhaps +set Transfer-Encoding: chunked.

    + +

    NOTE: the request is not complete. This method only sends the header of +the request. One needs to call request.end() to finalize the request and +retrieve the response. (This sounds convoluted but it provides a chance for +the user to stream a body to the server with request.write().)

    + +

    client.verifyPeer()

    + +

    Returns true or false depending on the validity of the server's certificate in the context of the defined or default list of trusted CA certificates.

    + +

    client.getPeerCertificate()

    + +

    Returns a JSON structure detailing the server's certificate, containing a dictionary with keys for the certificate 'subject', 'issuer', 'valid_from' and 'valid_to'

    + +

    http.ClientRequest

    + +

    This object is created internally and returned from the request() method +of a http.Client. It represents an in-progress request whose header has +already been sent.

    + +

    To get the response, add a listener for 'response' to the request object. +'response' will be emitted from the request object when the response +headers have been received. The 'response' event is executed with one +argument which is an instance of http.ClientResponse.

    + +

    During the 'response' event, one can add listeners to the +response object; particularly to listen for the 'data' event. Note that +the 'response' event is called before any part of the response body is received, +so there is no need to worry about racing to catch the first part of the +body. As long as a listener for 'data' is added during the 'response' +event, the entire body will be caught.

    + +
    // Good
    +request.addListener('response', function (response) {
    +  response.addListener('data', function (chunk) {
    +    sys.puts('BODY: ' + chunk);
    +  });
    +});
    +
    +// Bad - misses all or part of the body
    +request.addListener('response', function (response) {
    +  setTimeout(function () {
    +    response.addListener('data', function (chunk) {
    +      sys.puts('BODY: ' + chunk);
    +    });
    +  }, 10);
    +});
    +
    + +

    This is a writable stream.

    + +

    This is an EventEmitter with the following events:

    + +

    Event 'response'

    + +

    function (response) { }

    + +

    Emitted when a response is received to this request. This event is emitted only once. The +response argument will be an instance of http.ClientResponse.

    + +

    request.write(chunk, encoding='ascii')

    + +

    Sends a chunk of the body. By calling this method +many times, the user can stream a request body to a +server--in that case it is suggested to use the +['Transfer-Encoding', 'chunked'] header line when +creating the request.

    + +

    The chunk argument should be an array of integers +or a string.

    + +

    The encoding argument is optional and only +applies when chunk is a string. The encoding +argument should be either 'utf8' or +'ascii'. By default the body uses ASCII encoding, +as it is faster.

    + +

    request.end()

    + +

    Finishes sending the request. If any parts of the body are +unsent, it will flush them to the stream. If the request is +chunked, this will send the terminating '0\r\n\r\n'.

    + +

    http.ClientResponse

    + +

    This object is created when making a request with http.Client. It is +passed to the 'response' event of the request object.

    + +

    The response implements the readable stream interface.

    + +

    Event: 'data'

    + +

    function (chunk) {}

    + +

    Emitted when a piece of the message body is received.

    + +
    Example: A chunk of the body is given as the single
    +argument. The transfer-encoding has been decoded.  The
    +body chunk a String.  The body encoding is set with
    +`response.setBodyEncoding()`.
    +
    + +

    Event: 'end'

    + +

    function () {}

    + +

    Emitted exactly once for each message. No arguments. After +emitted no other events will be emitted on the response.

    + +

    response.statusCode

    + +

    The 3-digit HTTP response status code. E.G. 404.

    + +

    response.httpVersion

    + +

    The HTTP version of the connected-to server. Probably either +'1.1' or '1.0'. +Also response.httpVersionMajor is the first integer and +response.httpVersionMinor is the second.

    + +

    response.headers

    + +

    The response headers.

    + +

    response.setEncoding(encoding)

    + +

    Set the encoding for the response body. Either 'utf8' or 'binary'. +Defaults to 'binary'.

    + +

    response.pause()

    + +

    Pauses response from emitting events. Useful to throttle back a download.

    + +

    response.resume()

    + +

    Resumes a paused response.

    + +

    response.client

    + +

    A reference to the http.Client that this response belongs to.

    + +

    net.Server

    + +

    This class is used to create a TCP or UNIX server.

    + +

    Here is an example of a echo server which listens for connections +on port 8124:

    + +
    var net = require('net');
    +var server = net.createServer(function (stream) {
    +  stream.setEncoding('utf8');
    +  stream.addListener('connect', function () {
    +    stream.write('hello\r\n');
    +  });
    +  stream.addListener('data', function (data) {
    +    stream.write(data);
    +  });
    +  stream.addListener('end', function () {
    +    stream.write('goodbye\r\n');
    +    stream.end();
    +  });
    +});
    +server.listen(8124, 'localhost');
    +
    + +

    To listen on the socket '/tmp/echo.sock', the last line would just be +changed to

    + +
    server.listen('/tmp/echo.sock');
    +
    + +

    This is an EventEmitter with the following events:

    + +

    Event: 'connection'

    + +

    function (stream) {}

    + +

    Emitted when a new connection is made. stream is an instance of +net.Stream.

    + +

    Event: 'close'

    + +

    function () {}

    + +

    Emitted when the server closes.

    + +

    net.createServer(connectionListener)

    + +

    Creates a new TCP server. The connection_listener argument is +automatically set as a listener for the 'connection' event.

    + +

    server.listen(port, host=null, callback=null)

    + +

    Begin accepting connections on the specified port and host. If the +host is omitted, the server will accept connections directed to any +IPv4 address (INADDR_ANY).

    + +

    This function is asynchronous. The last parameter callback will be called +when the server has been bound.

    + +

    server.listen(path, callback=null)

    + +

    Start a UNIX socket server listening for connections on the given path.

    + +

    This function is asynchronous. The last parameter callback will be called +when the server has been bound.

    + +

    server.close()

    + +

    Stops the server from accepting new connections. This function is +asynchronous, the server is finally closed when the server emits a 'close' +event.

    + +

    net.Stream

    + +

    This object is an abstraction of of a TCP or UNIX socket. net.Stream +instance implement a duplex stream interface. They can be created by the +user and used as a client (with connect()) or they can be created by Node +and passed to the user through the 'connection' event of a server.

    + +

    net.Stream instances are an EventEmitters with the following events:

    + +

    Event: 'connect'

    + +

    function () { }

    + +

    Emitted when a stream connection successfully is established. +See connect().

    + +

    Event: 'secure'

    + +

    function () { }

    + +

    Emitted when a stream connection successfully establishes a HTTPS handshake with its peer.

    + +

    Event: 'data'

    + +

    function (data) { }

    + +

    Emitted when data is received. The argument data will be a Buffer or +String. Encoding of data is set by stream.setEncoding(). +(See the section on Readable Streams for more infromation.)

    + +

    Event: 'end'

    + +

    function () { }

    + +

    Emitted when the other end of the stream sends a FIN packet. After this is +emitted the readyState will be 'writeOnly'. One should probably just +call stream.end() when this event is emitted.

    + +

    Event: 'timeout'

    + +

    function () { }

    + +

    Emitted if the stream times out from inactivity. This is only to notify that +the stream has been idle. The user must manually close the connection.

    + +

    See also: stream.setTimeout()

    + +

    Event: 'drain'

    + +

    function () { }

    + +

    Emitted when the write buffer becomes empty. Can be used to throttle uploads.

    + +

    Event: 'error'

    + +

    function (exception) { }

    + +

    Emitted when an error occurs. The 'close' event will be called directly +following this event.

    + +

    Event: 'close'

    + +

    function () { }

    + +

    Emitted once the stream is fully closed. The argument had_error is a boolean which says if +the stream was closed due to a transmission +error.

    + +

    net.createConnection(port, host='127.0.0.1')

    + +

    Construct a new stream object and opens a stream to the specified port +and host. If the second parameter is omitted, localhost is assumed.

    + +

    When the stream is established the 'connect' event will be emitted.

    + +

    stream.connect(port, host='127.0.0.1')

    + +

    Opens a stream to the specified port and host. createConnection() +also opens a stream; normally this method is not needed. Use this only if +a stream is closed and you want to reuse the object to connect to another +server.

    + +

    This function is asynchronous. When the 'connect' event is emitted the +stream is established. If there is a problem connecting, the 'connect' +event will not be emitted, the 'error' event will be emitted with +the exception.

    + +

    stream.remoteAddress

    + +

    The string representation of the remote IP address. For example, +'74.125.127.100' or '2001:4860:a005::68'.

    + +

    This member is only present in server-side connections.

    + +

    stream.readyState

    + +

    Either 'closed', 'open', 'opening', 'readOnly', or 'writeOnly'.

    + +

    stream.setEncoding(encoding)

    + +

    Sets the encoding (either 'ascii', 'utf8', or 'binary') for data that is +received.

    + +

    stream.setSecure(credentials)

    + +

    Enables HTTPS support for the stream, with the crypto module credentials specifying the private key and certificate of the stream, and optionally the CA certificates for use in peer authentication.

    + +

    If the credentials hold one ore more CA certificates, then the stream will request for the peer to submit a client certificate as part of the HTTPS connection handshake. The validity and content of this can be accessed via verifyPeer() and getPeerCertificate().

    + +

    stream.verifyPeer()

    + +

    Returns true or false depending on the validity of the peers's certificate in the context of the defined or default list of trusted CA certificates.

    + +

    stream.getPeerCertificate()

    + +

    Returns a JSON structure detailing the peer's certificate, containing a dictionary with keys for the certificate 'subject', 'issuer', 'valid_from' and 'valid_to'

    + +

    stream.write(data, encoding='ascii')

    + +

    Sends data on the stream. The second parameter specifies the encoding in +the case of a string--it defaults to ASCII because encoding to UTF8 is rather +slow.

    + +

    Returns true if the entire data was flushed successfully to the kernel +buffer. Returns false if all or part of the data was queued in user memory. +'drain' will be emitted when the buffer is again free.

    + +

    stream.end()

    + +

    Half-closes the stream. I.E., it sends a FIN packet. It is possible the +server will still send some data. After calling this readyState will be +'readOnly'.

    + +

    stream.destroy()

    + +

    Ensures that no more I/O activity happens on this stream. Only necessary in +case of errors (parse error or so).

    + +

    stream.pause()

    + +

    Pauses the reading of data. That is, 'data' events will not be emitted. +Useful to throttle back an upload.

    + +

    stream.resume()

    + +

    Resumes reading after a call to pause().

    + +

    stream.setTimeout(timeout)

    + +

    Sets the stream to timeout after timeout milliseconds of inactivity on +the stream. By default net.Stream do not have a timeout.

    + +

    When an idle timeout is triggered the stream will receive a 'timeout' +event but the connection will not be severed. The user must manually end() +or destroy() the stream.

    + +

    If timeout is 0, then the existing idle timeout is disabled.

    + +

    stream.setNoDelay(noDelay=true)

    + +

    Disables the Nagle algorithm. By default TCP connections use the Nagle +algorithm, they buffer data before sending it off. Setting noDelay will +immediately fire off data each time stream.write() is called.

    + +

    stream.setKeepAlive(enable=false, initialDelay)

    + +

    Enable/disable keep-alive functionality, and optionally set the initial +delay before the first keepalive probe is sent on an idle stream. +Set initialDelay (in milliseconds) to set the delay between the last +data packet received and the first keepalive probe. Setting 0 for +initialDelay will leave the value unchanged from the default +(or previous) setting.

    + +

    Crypto

    + +

    Use require('crypto') to access this module.

    + +

    The crypto module requires OpenSSL to be available on the underlying platform. It offers a way of encapsulating secure credentials to be used as part of a secure HTTPS net or http connection.

    + +

    It also offers a set of wrappers for OpenSSL's hash, hmac, cipher, decipher, sign and verify methods.

    + +

    crypto.createCredentials(details)

    + +

    Creates a credentials object, with the optional details being a dictionary with keys:

    + +

    key : a string holding the PEM encoded private key

    + +

    cert : a string holding the PEM encoded certificate

    + +

    ca : either a string or list of strings of PEM encoded CA certificates to trust.

    + +

    If no 'ca' details are given, then node.js will use the default publicly trusted list of CAs as given in +http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt

    + +

    crypto.createHash(algorithm)

    + +

    Creates and returns a hash object, a cryptographic hash with the given algorithm which can be used to generate hash digests.

    + +

    algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are sha1, md5, sha256, sha512, etc. On recent releases, openssl list-message-digest-algorithms will display the available digest algorithms.

    + +

    hash.update(data)

    + +

    Updates the hash content with the given data. This can be called many times with new data as it is streamed.

    + +

    hash.digest(encoding)

    + +

    Calculates the digest of all of the passed data to be hashed. The encoding can be 'hex', 'binary' or 'base64'.

    + +

    crypto.createHmac(algorithm, key)

    + +

    Creates and returns a hmac object, a cryptographic hmac with the given algorithm and key.

    + +

    algorithm is dependent on the available algorithms supported by OpenSSL - see createHash above. +key is the hmac key to be used.

    + +

    hmac.update(data)

    + +

    Update the hmac content with the given data. This can be called many times with new data as it is streamed.

    + +

    hmac.digest(encoding)

    + +

    Calculates the digest of all of the passed data to the hmac. The encoding can be 'hex', 'binary' or 'base64'.

    + +

    crypto.createCipher(algorithm, key)

    + +

    Creates and returns a cipher object, with the given algorithm and key.

    + +

    algorithm is dependent on OpenSSL, examples are aes192, etc. On recent releases, openssl list-cipher-algorithms will display the available cipher algorithms.

    + +

    cipher.update(data, input_encoding, output_encoding)

    + +

    Updates the cipher with data, the encoding of which is given in input_encoding and can be 'utf8', 'ascii' or 'binary'. The output_encoding specifies the output format of the enciphered data, and can be 'binary', 'base64' or 'hex'.

    + +

    Returns the enciphered contents, and can be called many times with new data as it is streamed.

    + +

    cipher.final(output_encoding)

    + +

    Returns any remaining enciphered contents, with output_encoding as update above.

    + +

    crypto.createDecipher(algorithm, key)

    + +

    Creates and returns a decipher object, with the given algorithm and key. This is the mirror of the cipher object above.

    + +

    decipher.update(data, input_encoding, output_encoding)

    + +

    Updates the decipher with data, which is encoded in 'binary', 'base64' or 'hex'. The output_decoding specifies in what format to return the deciphered plaintext - either 'binary', 'ascii' or 'utf8'.

    + +

    decipher.final(output_encoding)

    + +

    Returns any remaining plaintext which is deciphered, with `output_encoding' as update above.

    + +

    crypto.createSign(algorithm)

    + +

    Creates and returns a signing object, with the given algorithm. On recent OpenSSL releases, openssl list-public-key-algorithms will display the available signing algorithms. Examples are 'RSA-SHA256'.

    + +

    signer.update(data)

    + +

    Updates the signer object with data. This can be called many times with new data as it is streamed.

    + +

    signer.sign(private_key, output_format)

    + +

    Calculates the signature on all the updated data passed through the signer. private_key is a string containing the PEM encoded private key for signing.

    + +

    Returns the signature in output_format which can be 'binary', 'hex' or 'base64'

    + +

    crypto.createVerify(algorithm)

    + +

    Creates and returns a verification object, with the given algorithm. This is the mirror of the signing object above.

    + +

    verifier.update(data)

    + +

    Updates the verifyer object with data. This can be called many times with new data as it is streamed.

    + +

    verifier.verify(public_key, signature, signature_format)

    + +

    Verifies the signed data by using the public_key which is a string containing the PEM encoded public key, and signature, which is the previously calculates signature for the data, in the signature_format which can be 'binary', 'hex' or 'base64'.

    + +

    Returns true or false depending on the validity of the signature for the data and public key.

    + +

    DNS

    + +

    Use require('dns') to access this module.

    + +

    Here is an example which resolves 'www.google.com' then reverse +resolves the IP addresses which are returned.

    + +
    var dns = require('dns'),
    +    sys = require('sys');
    +
    +dns.resolve4('www.google.com', function (err, addresses) {
    +  if (err) throw err;
    +
    +  sys.puts('addresses: ' + JSON.stringify(addresses));
    +
    +  for (var i = 0; i < addresses.length; i++) {
    +    var a = addresses[i];
    +    dns.reverse(a, function (err, domains) {
    +      if (err) {
    +        sys.puts('reverse for ' + a + ' failed: ' + 
    +          err.message);
    +      } else {
    +        sys.puts('reverse for ' + a + ': ' + 
    +          JSON.stringify(domains));
    +      }
    +    });
    +  }
    +});
    +
    + +

    dns.resolve(domain, rrtype = 'A', callback)

    + +

    Resolves a domain (e.g. 'google.com') into an array of the record types +specified by rrtype. Valid rrtypes are A (IPV4 addresses), AAAA (IPV6 +addresses), MX (mail exchange records), TXT (text records), SRV (SRV +records), and PTR (used for reverse IP lookups).

    + +

    The callback has arguments (err, addresses). The type of each item +in addresses is determined by the record type, and described in the +documentation for the corresponding lookup methods below.

    + +

    On error, err would be an instanceof Error object, where err.errno is +one of the error codes listed below and err.message is a string describing +the error in English.

    + +

    dns.resolve4(domain, callback)

    + +

    The same as dns.resolve(), but only for IPv4 queries (A records). +addresses is an array of IPv4 addresses (e.g.
    +['74.125.79.104', '74.125.79.105', '74.125.79.106']).

    + +

    dns.resolve6(domain, callback)

    + +

    The same as dns.resolve4() except for IPv6 queries (an AAAA query).

    + +

    dns.resolveMx(domain, callback)

    + +

    The same as dns.resolve(), but only for mail exchange queries (MX records).

    + +

    addresses is an array of MX records, each with a priority and an exchange +attribute (e.g. [{'priority': 10, 'exchange': 'mx.example.com'},...]).

    + +

    dns.resolveTxt(domain, callback)

    + +

    The same as dns.resolve(), but only for text queries (TXT records). +addresses is an array of the text records available for domain (e.g., +['v=spf1 ip4:0.0.0.0 ~all']).

    + +

    dns.resolveSrv(domain, callback)

    + +

    The same as dns.resolve(), but only for service records (SRV records). +addresses is an array of the SRV records available for domain. Properties +of SRV records are priority, weight, port, and name (e.g., +[{'priority': 10, {'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...]).

    + +

    dns.reverse(ip, callback)

    + +

    Reverse resolves an ip address to an array of domain names.

    + +

    The callback has arguments (err, domains).

    + +

    If there an an error, err will be non-null and an instanceof the Error +object.

    + +

    Each DNS query can return an error code.

    + +
      +
    • dns.TEMPFAIL: timeout, SERVFAIL or similar.
    • +
    • dns.PROTOCOL: got garbled reply.
    • +
    • dns.NXDOMAIN: domain does not exists.
    • +
    • dns.NODATA: domain exists but no data of reqd type.
    • +
    • dns.NOMEM: out of memory while processing.
    • +
    • dns.BADQUERY: the query is malformed.
    • +
    + + +

    Assert

    + +

    This module is used for writing unit tests for your applications, you can +access it with require('assert').

    + +

    assert.fail(actual, expected, message, operator)

    + +

    Tests if actual is equal to expected using the operator provided.

    + +

    assert.ok(value, message)

    + +

    Tests if value is a true value, it is equivalent to assert.equal(true, value, message);

    + +

    assert.equal(actual, expected, message)

    + +

    Tests shallow, coercive equality with the equal comparison operator ( == ).

    + +

    assert.notEqual(actual, expected, message)

    + +

    Tests shallow, coercive non-equality with the not equal comparison operator ( != ).

    + +

    assert.deepEqual(actual, expected, message)

    + +

    Tests for deep equality.

    + +

    assert.notDeepEqual(actual, expected, message)

    + +

    Tests for any deep inequality.

    + +

    assert.strictEqual(actual, expected, message)

    + +

    Tests strict equality, as determined by the strict equality operator ( === )

    + +

    assert.notStrictEqual(actual, expected, message)

    + +

    Tests strict non-equality, as determined by the strict not equal operator ( !== )

    + +

    assert.throws(block, error, message)

    + +

    Expects block to throw an error.

    + +

    assert.doesNotThrow(block, error, message)

    + +

    Expects block not to throw an error.

    + +

    assert.ifError(value)

    + +

    Tests if value is not a false value, throws if it is a true value. Useful when testing the first argument, error in callbacks.

    + +

    Path

    + +

    This module contains utilities for dealing with file paths. Use +require('path') to use it. It provides the following methods:

    + +

    path.join(/ path1, path2, ... /)

    + +

    Join all arguments together and resolve the resulting path. Example:

    + +
    node> require('path').join(
    +...   '/foo', 'bar', 'baz/asdf', 'quux', '..')
    +'/foo/bar/baz/asdf'
    +
    + +

    path.normalizeArray(arr)

    + +

    Normalize an array of path parts, taking care of '..' and '.' parts. Example:

    + +
    path.normalizeArray(['', 
    +  'foo', 'bar', 'baz', 'asdf', 'quux', '..'])
    +// returns
    +[ '', 'foo', 'bar', 'baz', 'asdf' ]
    +
    + +

    path.normalize(p)

    + +

    Normalize a string path, taking care of '..' and '.' parts. Example:

    + +
    path.normalize('/foo/bar/baz/asdf/quux/..')
    +// returns
    +'/foo/bar/baz/asdf'
    +
    + +

    path.dirname(p)

    + +

    Return the directory name of a path. Similar to the Unix dirname command. Example:

    + +
    path.dirname('/foo/bar/baz/asdf/quux')
    +// returns
    +'/foo/bar/baz/asdf'
    +
    + +

    path.basename(p, ext)

    + +

    Return the last portion of a path. Similar to the Unix basename command. Example:

    + +
    path.basename('/foo/bar/baz/asdf/quux.html')
    +// returns
    +'quux.html'
    +
    +path.basename('/foo/bar/baz/asdf/quux.html', '.html')
    +// returns
    +'quux'
    +
    + +

    path.extname(p)

    + +

    Return the extension of the path. Everything after the last '.' in the last portion +of the path. If there is no '.' in the last portion of the path or the only '.' is +the first character, then it returns an empty string. Examples:

    + +
    path.extname('index.html')
    +// returns 
    +'.html'
    +
    +path.extname('index')
    +// returns
    +''
    +
    + +

    path.exists(p, callback)

    + +

    Test whether or not the given path exists. Then, call the callback argument with either true or false. Example:

    + +
    path.exists('/etc/passwd', function (exists) {
    +  sys.debug(exists ? "it's there" : "no passwd!");
    +});
    +
    + +

    URL

    + +

    This module has utilities for URL resolution and parsing. +Call require('url') to use it.

    + +

    Parsed URL objects have some or all of the following fields, depending on +whether or not they exist in the URL string. Any parts that are not in the URL +string will not be in the parsed object. Examples are shown for the URL

    + +

    'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'

    + +
      +
    • href

      + +

      The full URL that was originally parsed. Example: +'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'

    • +
    • protocol

      + +

      The request protocol. Example: 'http:'

    • +
    • host

      + +

      The full host portion of the URL, including port and authentication information. Example: +'user:pass@host.com:8080'

    • +
    • auth

      + +

      The authentication information portion of a URL. Example: 'user:pass'

    • +
    • hostname

      + +

      Just the hostname portion of the host. Example: 'host.com'

    • +
    • port

      + +

      The port number portion of the host. Example: '8080'

    • +
    • pathname

      + +

      The path section of the URL, that comes after the host and before the query, including the initial slash if present. Example: '/p/a/t/h'

    • +
    • search

      + +

      The 'query string' portion of the URL, including the leading question mark. Example: '?query=string'

    • +
    • query

      + +

      Either the 'params' portion of the query string, or a querystring-parsed object. Example: +'query=string' or {'query':'string'}

    • +
    • hash

      + +

      The 'fragment' portion of the URL including the pound-sign. Example: '#hash'

    • +
    + + +

    The following methods are provided by the URL module:

    + +

    url.parse(urlStr, parseQueryString=false)

    + +

    Take a URL string, and return an object. Pass true as the second argument to also parse +the query string using the querystring module.

    + +

    url.format(urlObj)

    + +

    Take a parsed URL object, and return a formatted URL string.

    + +

    url.resolve(from, to)

    + +

    Take a base URL, and a href URL, and resolve them as a browser would for an anchor tag.

    + +

    Query String

    + +

    This module provides utilities for dealing with query strings. It provides the following methods:

    + +

    querystring.stringify(obj, sep='&', eq='=', munge=true)

    + +

    Serialize an object to a query string. Optionally override the default separator and assignment characters. +Example:

    + +
    querystring.stringify({foo: 'bar'})
    +// returns
    +'foo=bar'
    +
    +querystring.stringify({foo: 'bar', baz: 'bob'}, ';', ':')
    +// returns
    +'foo:bar;baz:bob'
    +
    + +

    By default, this function will perform PHP/Rails-style parameter mungeing for arrays and objects used as +values within obj. +Example:

    + +
    querystring.stringify({foo: 'bar', foo: 'baz', foo: 'boz'})
    +// returns
    +'foo[]=bar&foo[]=baz&foo[]=boz'
    +
    +querystring.stringify({foo: {bar: 'baz'}})
    +// returns
    +'foo[bar]=baz'
    +
    + +

    If you wish to disable the array mungeing (e.g. when generating parameters for a Java servlet), you +can set the munge argument to false. +Example:

    + +
    querystring.stringify({foo: 'bar', foo: 'baz', foo: 'boz'}, '&', '=', false)
    +// returns
    +'foo=bar&foo=baz&foo=boz'
    +
    + +

    Note that when munge is false, parameter names with object values will still be munged.

    + +

    querystring.parse(str, sep='&', eq='=')

    + +

    Deserialize a query string to an object. Optionally override the default separator and assignment characters.

    + +
    querystring.parse('a=b&b=c')
    +// returns
    +{ 'a': 'b'
    +, 'b': 'c'
    +}
    +
    + +

    This function can parse both munged and unmunged query strings (see stringify for details).

    + +

    querystring.escape

    + +

    The escape function used by querystring.stringify, provided so that it could be overridden if necessary.

    + +

    querystring.unescape

    + +

    The unescape function used by querystring.parse, provided so that it could be overridden if necessary.

    + +

    REPL

    + +

    A Read-Eval-Print-Loop (REPL) is available both as a standalone program and easily +includable in other programs. REPL provides a way to interactively run +JavaScript and see the results. It can be used for debugging, testing, or +just trying things out.

    + +

    By executing node without any arguments from the command-line you will be +dropped into the REPL. It has simplistic emacs line-editting.

    + +
    mjr:~$ node
    +Type '.help' for options.
    +node> a = [ 1, 2, 3];
    +[ 1, 2, 3 ]
    +node> a.forEach(function (v) {
    +...   sys.puts(v);
    +...   });
    +1
    +2
    +3
    +
    + +

    For advanced line-editors, start node with the environmental variable NODE_NO_READLINE=1. +This will start the REPL in canonical terminal settings which will allow you to use with rlwrap.

    + +

    For example, you could add this to your bashrc file:

    + +
    alias node="env NODE_NO_READLINE=1 rlwrap node"
    +
    + +

    repl.start(prompt, stream)

    + +

    Starts a REPL with prompt as the prompt and stream for all I/O. prompt +is optional and defaults to node>. stream is optional and defaults to +process.openStdin().

    + +

    Multiple REPLs may be started against the same running instance of node. Each +will share the same global object but will have unique I/O.

    + +

    Here is an example that starts a REPL on stdin, a Unix socket, and a TCP socket:

    + +
    var sys = require("sys"),
    +    net = require("net"),
    +    repl = require("repl");
    +
    +connections = 0;
    +
    +repl.start("node via stdin> ");
    +
    +net.createServer(function (socket) {
    +  connections += 1;
    +  repl.start("node via Unix socket> ", socket);
    +}).listen("/tmp/node-repl-sock");
    +
    +net.createServer(function (socket) {
    +  connections += 1;
    +  repl.start("node via TCP socket> ", socket);
    +}).listen(5001);
    +
    + +

    Running this program from the command line will start a REPL on stdin. Other +REPL clients may connect through the Unix socket or TCP socket. telnet is useful +for connecting to TCP sockets, and socat can be used to connect to both Unix and +TCP sockets.

    + +

    By starting a REPL from a Unix socket-based server instead of stdin, you can +connect to a long-running node process without restarting it.

    + +

    REPL Features

    + +

    Inside the REPL, Control+D will exit. Multi-line expressions can be input.

    + +

    The special variable _ (underscore) contains the result of the last expression.

    + +
    node> [ "a", "b", "c" ]
    +[ 'a', 'b', 'c' ]
    +node> _.length 
    +3
    +node> _ += 1
    +4
    +
    + +

    The REPL provides access to any variables in the global scope. You can expose a variable +to the REPL explicitly by assigning it to the scope object associated with each +REPLServer. For example:

    + +
    // repl_test.js
    +var repl = require("repl"),
    +    msg = "message";
    +
    +repl.start().scope.m = msg;
    +
    + +

    Things in the scope object appear as local within the REPL:

    + +
    mjr:~$ node repl_test.js 
    +node> m
    +'message'
    +
    + +

    There are a few special REPL commands:

    + +
      +
    • .break - While inputting a multi-line expression, sometimes you get lost or just don't care +about completing it. .break will start over.

    • +
    • .clear - Resets the scope object to an empty object and clears any multi-line expression.

    • +
    • .exit - Close the I/O stream, which will cause the REPL to exit.

    • +
    • .help - Show this list of special commands.

    • +
    + + +

    Modules

    + +

    Node uses the CommonJS module system.

    + +

    Node has a simple module loading system. In Node, files and modules are in +one-to-one correspondence. As an example, foo.js loads the module +circle.js in the same directory.

    + +

    The contents of foo.js:

    + +
    var circle = require('./circle'),
    +    sys = require('sys');
    +sys.puts( 'The area of a circle of radius 4 is '
    +  + circle.area(4));
    +
    + +

    The contents of circle.js:

    + +
    var PI = 3.14;
    +
    +exports.area = function (r) {
    +  return PI * r * r;
    +};
    +
    +exports.circumference = function (r) {
    +  return 2 * PI * r;
    +};
    +
    + +

    The module circle.js has exported the functions area() and +circumference(). To export an object, add to the special exports +object. (Alternatively, one can use this instead of exports.) Variables +local to the module will be private. In this example the variable PI is +private to circle.js. The function puts() comes from the module 'sys', +which is a built-in module. Modules which are not prefixed by './' are +built-in module--more about this later.

    + +

    A module prefixed with './' is relative to the file calling require(). +That is, circle.js must be in the same directory as foo.js for +require('./circle') to find it.

    + +

    Without the leading './', like require('assert') the module is searched +for in the require.paths array. require.paths on my system looks like +this:

    + +

    [ '/home/ryan/.node_libraries' ]

    + +

    That is, when require('assert') is called Node looks for:

    + +
      +
    • 1: /home/ryan/.node_libraries/assert.js
    • +
    • 2: /home/ryan/.node_libraries/assert.node
    • +
    • 3: /home/ryan/.node_libraries/assert/index.js
    • +
    • 4: /home/ryan/.node_libraries/assert/index.node
    • +
    + + +

    interrupting once a file is found. Files ending in '.node' are binary Addon +Modules; see 'Addons' below. 'index.js' allows one to package a module as +a directory.

    + +

    require.paths can be modified at runtime by simply unshifting new +paths onto it, or at startup with the NODE_PATH environmental +variable (which should be a list of paths, colon separated).

    + +

    Addons

    + +

    Addons are dynamically linked shared objects. They can provide glue to C and +C++ libraries. The API (at the moment) is rather complex, involving +knowledge of several libraries:

    + +
      +
    • V8 JavaScript, a C++ library. Used for interfacing with JavaScript: +creating objects, calling functions, etc. Documented mostly in the +v8.h header file (deps/v8/include/v8.h in the Node source tree).

    • +
    • libev, C event loop library. Anytime one needs to wait for a file +descriptor to become readable, wait for a timer, or wait for a signal to +received one will need to interface with libev. That is, if you perform +any I/O, libev will need to be used. Node uses the EV_DEFAULT event +loop. Documentation can be found http:/cvs.schmorp.de/libev/ev.html[here].

    • +
    • libeio, C thread pool library. Used to execute blocking POSIX system +calls asynchronously. Mostly wrappers already exist for such calls, in +src/file.cc so you will probably not need to use it. If you do need it, +look at the header file deps/libeio/eio.h.

    • +
    • Internal Node libraries. Most importantly is the node::ObjectWrap +class which you will likely want to derive from.

    • +
    • Others. Look in deps/ for what else is available.

    • +
    + + +

    Node statically compiles all its dependencies into the executable. When +compiling your module, you don't need to worry about linking to any of these +libraries.

    + +

    To get started let's make a small Addon which does the following except in +C++:

    + +
    exports.hello = 'world';
    +
    + +

    To get started we create a file hello.cc:

    + +
    #include <v8.h>
    +
    +using namespace v8;
    +
    +extern 'C' void
    +init (Handle<Object> target) 
    +{
    +  HandleScope scope;
    +  target->Set(String::New("hello"), String::New("World"));
    +}
    +
    + +

    This source code needs to be built into hello.node, the binary Addon. To +do this we create a file called wscript which is python code and looks +like this:

    + +
    srcdir = '.'
    +blddir = 'build'
    +VERSION = '0.0.1'
    +
    +def set_options(opt):
    +  opt.tool_options('compiler_cxx')
    +
    +def configure(conf):
    +  conf.check_tool('compiler_cxx')
    +  conf.check_tool('node_addon')
    +
    +def build(bld):
    +  obj = bld.new_task_gen('cxx', 'shlib', 'node_addon')
    +  obj.target = 'hello'
    +  obj.source = 'hello.cc'
    +
    + +

    Running node-waf configure build will create a file +build/default/hello.node which is our Addon.

    + +

    node-waf is just http://code.google.com/p/waf/[WAF], the python-based build system. node-waf is +provided for the ease of users.

    + +

    All Node addons must export a function called init with this signature:

    + +
    extern 'C' void init (Handle<Object> target)
    +
    + +

    For the moment, that is all the documentation on addons. Please see +http://github.com/ry/node_postgres for a real example.

    +
    +
    + + + + + + \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/getelement.html b/node_modules/jsdom/node_modules/htmlparser/testdata/getelement.html new file mode 100644 index 0000000..423d135 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/getelement.html @@ -0,0 +1,3460 @@ + + + + + + + Stack Overflow + + + + + + + + + + + + + + + + +
    + + + + + +
    +
    + + +
    + +
    + +
    +

    Top Questions

    + +
    +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    11
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    10
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    0
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    5
    +
    answers
    +
    +
    +
    88
    +
    views
    +
    +
    +
    +

    how to create folder ?

    + +
    + +
    +
    + + 20s ago + Luc M 1,261 +
    +
    +
    + +
    +
    +
    +
    4
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    11
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    18
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    4
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    -2
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    49
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    44
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    6
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    3
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    3
    +
    kviews
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    1
    +
    view
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    41
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    1
    +
    view
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    20
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    33
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    18
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    12
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    10
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    18
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    9
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    6
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    5
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    7
    +
    votes
    +
    +
    +
    9
    +
    answers
    +
    +
    +
    155
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    1
    +
    view
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    1
    +
    view
    +
    +
    +
    +

    Drupal Features include Theme

    + +
    + +
    +
    + 2m ago + Linda 93 +
    +
    +
    + +
    +
    +
    +
    3
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    29
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    8
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    4
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    8
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    34
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    1
    +
    view
    +
    +
    +
    +

    writing hbase reports

    + + +
    + 3m ago + sammy 1 +
    +
    +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    7
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    14
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    8
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    23
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    14
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    9
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    14
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    12
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    5
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    14
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    50
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    6
    +
    answers
    +
    +
    +
    100
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    13
    +
    answers
    +
    +
    +
    133
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    5
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    5
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    24
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    2
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    14
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    4
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    32
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    10
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    5
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    39
    +
    votes
    +
    +
    +
    16
    +
    answers
    +
    +
    +
    16
    +
    kviews
    +
    +
    + +
    + +
    +
    +
    +
    3
    +
    votes
    +
    +
    +
    6
    +
    answers
    +
    +
    +
    1
    +
    kviews
    +
    +
    + +
    + +
    +
    +
    +
    6
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    72
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    18
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    4
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    20
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    2
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    6
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    2
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    17
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    -1
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    13
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    43
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    5
    +
    votes
    +
    +
    +
    5
    +
    answers
    +
    +
    +
    345
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    6
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    3
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    2
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    67
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    3
    +
    answers
    +
    +
    +
    11
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    kvotes
    +
    +
    +
    290
    +
    answers
    +
    +
    +
    101
    +
    kviews
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    23
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    5
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    28
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    33
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    7
    +
    votes
    +
    +
    +
    5
    +
    answers
    +
    +
    +
    2
    +
    kviews
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    13
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    3
    +
    votes
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    409
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    7
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    3
    +
    votes
    +
    +
    +
    4
    +
    answers
    +
    +
    +
    58
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    10
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    19
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    29
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    2
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    22
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    35
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    6
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    4
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    33
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    12
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    1
    +
    vote
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    12
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    1
    +
    answer
    +
    +
    +
    9
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    4
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    2
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    2
    +
    answers
    +
    +
    +
    32
    +
    views
    +
    +
    + +
    + +
    +
    +
    +
    0
    +
    votes
    +
    +
    +
    0
    +
    answers
    +
    +
    +
    3
    +
    views
    +
    +
    + +
    + +
    + +

    Looking for more? Browse the complete list of questions, or popular tags. Help us answer unanswered questions.

    + +
    + + + + + + +
    +
    + + + + + + + + + + + \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/htmlparser/testdata/trackerchecker.html b/node_modules/jsdom/node_modules/htmlparser/testdata/trackerchecker.html new file mode 100644 index 0000000..2dfb1a0 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/testdata/trackerchecker.html @@ -0,0 +1,2733 @@ + + + +www.trackerchecker.com - We check your trackers + + + + + + +
    + + + + + + +
    Home || Add a tracker || Latest trackers
    +
    + + +
    +follow us on Twitter
    +Follow trackerchecker on Twitter --> @trackerchecker. +
    +
    + + + + + + + +
    +We need your input!
    We're developing a new version of Trackerchecker and we want to know what functionality the users like to see in Trackerchecker V3! :) Contribute please and tell us what you like to see in Trackerchecker V3! +
    Name:
    E-mail:
    Suggestion
    +
    +
    + + +
    +
    + TrackerList
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     TrackerNameHistoryLastCheckedStatus
    1337x.orgview history2010-04-15 18:14:14Open
    420project.orgview history2010-04-15 18:23:46Closed
    acehd.netview history2010-04-15 18:05:34Closed
    acetorrents.netview history2010-04-15 18:09:10Open
    adult-cinema-network.netview history2010-04-15 18:21:21Open
    all4nothin.netview history2010-04-15 17:35:20Open
    allgirltorrents.comview history2010-04-15 17:45:50Closed
    allotracker.comview history2010-04-15 17:38:15Open
    appz.bitshock.orgview history2010-04-15 17:53:16Open
    appzuniverse.orgview history2010-04-15 17:49:10Closed
    arabfilms.orgview history2010-04-15 17:36:29Closed
    arabseries.orgview history2010-04-15 17:53:15Closed
    araditracker.comview history2010-04-15 17:37:17Closed
    arena-tr.comview history2010-04-15 18:21:22Closed
    arenabg.comview history2010-04-15 17:36:30Closed
    artofmisdirection.comview history2010-04-15 17:49:51Closed
    asiandvdclub.orgview history2010-04-15 17:35:13Open
    at-tracker.orgview history2010-04-15 18:09:40Offline
    atomico-torrent.comview history2010-04-15 18:00:09Closed
    audionews.ruview history2010-04-15 17:57:00Closed
    audiotracer.comview history2010-04-15 18:09:12Closed
    audiozonetorrents.comview history2010-04-15 18:22:18Open
    avatarbg.infoview history2010-04-15 18:09:40Closed
    awesome-hd.comview history2010-04-15 18:03:09Closed
    awesome-hd.netview history2010-04-15 18:09:25Closed
    baltracker.netview history2010-04-15 18:14:10Open
    bestmmatorrents.comview history2010-04-15 18:09:18Closed
    bestshare.roview history2010-04-15 17:37:02Closed
    bestxvid.orgview history2010-04-15 17:35:13Closed
    bit-hdtv.comview history2010-04-15 18:14:09Closed
    bitaddict.orgview history2010-04-15 17:45:11Closed
    bitchil.comview history2010-04-15 17:45:16Open
    bitflamers.comview history2010-04-15 18:21:13Closed
    bitgamer.comview history2010-04-15 18:05:52Closed
    bithq.orgview history2010-04-15 18:05:56Open
    bithumen.ath.cxview history2010-04-15 17:44:41Closed
    bitlove.huview history2010-04-15 17:35:02Closed
    bitme.orgview history2010-04-15 17:35:16Closed
    bitmetv.orgview history2010-04-15 17:40:50Closed
    bitmusic.huview history2010-04-15 18:22:56Closed
    bitnation.comview history2010-04-15 18:22:18Closed
    bitseduce.comview history2010-04-15 17:49:53Closed
    bitseek.orgview history2010-04-15 18:21:12Closed
    bitseek.orgview history2010-04-15 18:03:09Closed
    bitshock.orgview history2010-04-15 17:35:11Closed
    bitshock.orgview history2010-04-15 17:56:11Closed
    bitsoup.orgview history2010-04-15 17:35:20Closed
    bitSpyder.netview history2010-04-15 17:38:08Closed
    bittorrents.roview history2010-04-15 17:36:29Closed
    bitturk.netview history2010-04-15 18:09:18Closed
    biztorrents.comview history2010-04-15 17:45:11Open
    blackcats-games.netview history2010-04-15 17:36:28Closed
    blades-heaven.comview history2010-04-15 18:24:28Open
    blue-bytez.comview history2010-04-15 18:23:03Closed
    blue-whitegt.comview history2010-04-15 18:09:29Closed
    bmtorrents.netview history2010-04-15 17:38:13Closed
    bootytape.comview history2010-04-15 17:45:17Open
    bootytorrents.comview history2010-04-15 18:22:21Closed
    boxtorrents.comview history2010-04-15 18:22:19Closed
    bt.avistaz.comview history2010-04-15 18:14:10Closed
    bt.davka.infoview history2010-04-15 17:56:15Open
    bt.xbox-sky.ccview history2010-04-15 18:06:25Closed
    bt.xbox-sky.comview history2010-04-15 18:21:45Closed
    btgigs.infoview history2010-04-15 18:24:22Closed
    bwtorrents.comview history2010-04-15 18:05:56Closed
    bytelist.orgview history2010-04-15 17:53:12Offline
    cartoonchaos.orgview history2010-04-15 17:53:13Closed
    ccfbits.orgview history2010-04-15 17:56:59Closed
    chdbits.orgview history2010-04-15 18:13:08Open
    cheggit.net/view history2010-04-15 17:35:14Open
    chilebt.comview history2010-04-15 17:38:18Closed
    christiantorrents.comview history2010-04-15 17:56:54Closed
    chronictracker.comview history2010-04-15 18:00:23Closed
    cinema-obscura.comview history2010-04-15 18:17:13Closed
    cinemageddon.orgview history2010-04-15 17:45:11Closed
    cinematik.netview history2010-04-15 18:21:20Closed
    cleanvobs.orgview history2010-04-15 18:04:32Closed
    colombo-bt.orgview history2010-04-15 17:37:16Closed
    contego.wsview history2010-04-15 17:45:15Closed
    crazytorrent.euview history2010-04-15 18:22:17Closed
    czone.roview history2010-04-15 17:49:08Closed
    danger.lvview history2010-04-15 18:09:16Closed
    definitive-scene.comview history2010-04-15 18:23:46Open
    demonoid.comview history2010-04-15 17:45:48Closed
    devilwolfs.comview history2010-04-15 18:14:43Open
    diablotorrent.huview history2010-04-15 18:04:34Closed
    dididave.comview history2010-04-15 17:36:36Closed
    digitalhive.orgview history2010-04-15 17:45:10Open
    dimeadozen.orgview history2010-04-15 17:40:53Closed
    dnbtracker.orgview history2010-04-15 18:17:16Open
    docs.torrents.roview history2010-04-15 17:49:53Closed
    dvdseed.orgview history2010-04-15 17:56:11Closed
    dvdtreasure.euview history2010-04-15 17:53:16Closed
    ebookvortex.comview history2010-04-15 17:38:12Open
    eclipsetorrents.orgview history2010-04-15 17:40:45Closed
    egytorrent.comview history2010-04-15 17:49:09Closed
    egytorrent.comview history2010-04-15 18:16:07Open
    elbitz.netview history2010-04-15 18:09:35Closed
    elektronik.roview history2010-04-15 17:45:16Closed
    empornium.usview history2010-04-15 18:10:02Open
    eroticsource.plview history2010-04-15 18:06:22Closed
    estrenoslatinos.comview history2010-04-15 17:49:09Closed
    ethor.netview history2010-04-15 18:09:38Closed
    evopt.orgview history2010-04-15 17:49:03Closed
    Exigomusicview history2010-04-15 18:17:18Closed
    extremebits.orgview history2010-04-15 18:17:19Closed
    extremeshare.orgview history2010-04-15 17:36:35Open
    faplife.netview history2010-04-15 17:36:44Closed
    feedthe.netview history2010-04-15 17:37:23Closed
    filebits.orgview history2010-04-15 17:56:52Closed
    filelist.orgview history2010-04-15 18:09:17Closed
    filelist.roview history2010-04-15 17:49:53Closed
    filemp3.orgview history2010-04-15 17:36:43Closed
    fileporn.orgview history2010-04-15 17:53:11Closed
    flashtorrents.com.arview history2010-04-15 17:56:15Closed
    Free The Scene (FTS)view history2010-04-15 18:22:19Closed
    Fresh On TV (TvT)view history2010-04-15 18:17:13Open
    frztracker.sytes.netview history2010-04-15 18:03:49Closed
    fst.omnilounge.co.ukview history2010-04-15 17:36:29Closed
    fullcontactzone.comview history2010-04-15 18:03:17Closed
    gamecrook.comview history2010-04-15 17:42:03Closed
    gbvnet.roview history2010-04-15 17:38:09Closed
    gettorrents.orgview history2010-04-15 17:45:03Open
    gfxnews.ruview history2010-04-15 17:36:28Open
    gigatorrents.wsview history2010-04-15 18:14:10Closed
    glabella.orgview history2010-04-15 17:35:12Open
    globus-tracker.comview history2010-04-15 17:45:46Closed
    goem.orgview history2010-04-15 17:40:51Closed
    gormogon.comview history2010-04-15 18:09:29Open
    greek-tracker.comview history2010-04-15 17:35:15Closed
    grimetorrent.comview history2010-04-15 18:00:31Closed
    grtorrent.comview history2010-04-15 18:24:19Closed
    guiks.netview history2010-04-15 17:37:19Open
    h264torrents.comview history2010-04-15 18:21:54Closed
    h33t.comview history2010-04-15 18:17:20Open
    hd-bits.roview history2010-04-15 17:37:21Closed
    hd-torrents.orgview history2010-04-15 17:56:15Closed
    hdbits.orgview history2010-04-15 17:45:47Closed
    hdchina.orgview history2010-04-15 18:24:15Closed
    hdfrench.comview history2010-04-15 17:53:15Closed
    hdme.euview history2010-04-15 18:00:28Closed
    hdpre.comview history2010-04-15 17:35:03Closed
    hdsource.bizview history2010-04-15 18:04:34Closed
    hdstar.orgview history2010-04-15 17:45:12Closed
    hdvnbits.orgview history2010-04-15 17:49:50Closed
    heaventracker.orgview history2010-04-15 17:36:33Closed
    hermeticos.orgview history2010-04-15 18:14:44Closed
    horrorcharnel.kicks-ass.orgview history2010-04-15 18:21:15Closed
    hungercity.orgview history2010-04-15 17:34:14Open
    ifyounotknow.comview history2010-04-15 18:21:19Closed
    ilovetorrents.comview history2010-04-15 18:16:08Open
    indeep.bizview history2010-04-15 18:17:18Closed
    indietorrents.comview history2010-04-15 18:24:30Closed
    iplay.roview history2010-04-15 18:09:41Closed
    ipodnova.tvview history2010-04-15 17:36:36Closed
    iptorrents.comview history2010-04-15 18:23:02Closed
    joompalace.comview history2010-04-15 18:24:21Closed
    karagarga.netview history2010-04-15 18:09:40Closed
    killawaves.netview history2010-04-15 18:06:23Closed
    killawaves.orgview history2010-04-15 17:45:13Closed
    kinozal.wsview history2010-04-15 18:22:18Open
    kludd.comview history2010-04-15 18:00:23Closed
    lasttorrents.orgview history2010-04-15 18:09:38Open
    leecherslair.comview history2010-04-15 17:49:52Closed
    libble.comview history2010-04-15 18:03:18Closed
    libitina.netview history2010-04-15 18:21:16Closed
    linuxmafia.netview history2010-04-15 17:40:43Offline
    linuxtracker.orgview history2010-04-15 17:56:11Closed
    lostfilm.tvview history2010-04-15 18:03:20Open
    magiciantorrents.comview history2010-04-15 17:49:07Closed
    masterstb.comview history2010-04-15 17:34:17Closed
    mazetorrents.netview history2010-04-15 17:40:43Offline
    medioteka.comview history2010-04-15 17:37:02Closed
    mega-bits.comview history2010-04-15 17:34:16Closed
    mentol.roview history2010-04-15 17:36:42Closed
    metal.iplay.roview history2010-04-15 18:21:21Closed
    metalbits.orgview history2010-04-15 17:45:09Closed
    midnight-scene.comview history2010-04-15 18:23:43Closed
    midnight-torrents.comview history2010-04-15 17:38:14Closed
    mma-central.org.ukview history2010-04-15 17:36:27Closed
    mma-tracker.netview history2010-04-15 17:38:15Closed
    mp3nerds.orgview history2010-04-15 18:22:21Closed
    mucis-vid.comview history2010-04-15 17:35:16Closed
    musicplace.lvview history2010-04-15 17:53:17Closed
    mytorrent.tvview history2010-04-15 17:35:14Closed
    norbits.netview history2010-04-15 18:00:21Closed
    nordic-t.orgview history2010-04-15 18:00:22Closed
    nordicbits.orgview history2010-04-15 18:24:26Closed
    novaro.infoview history2010-04-15 18:16:56Closed
    novaro.infoview history2010-04-15 18:07:02Closed
    noviteti.comview history2010-04-15 18:09:35Closed
    ntorrents.netview history2010-04-15 17:34:13Closed
    nutorrent.comview history2010-04-15 18:14:45Open
    opennetwork.roview history2010-04-15 17:40:42Closed
    overtopropetorrents.comview history2010-04-15 17:49:55Closed
    ozone-torrents.orgview history2010-04-15 18:00:26Closed
    packme.inview history2010-04-15 17:49:54Closed
    Pedros btmusicview history2010-04-15 18:17:17Closed
    pianosheets.orgview history2010-04-15 18:17:16Closed
    pinkytorrents.comview history2010-04-15 18:03:11Open
    piranha.excom.usview history2010-04-15 17:40:43Open
    Pirate The Net (PtN)view history2010-04-15 17:40:45Closed
    piratebits.orgview history2010-04-15 17:44:14Closed
    piratefiles.seview history2010-04-15 18:17:11Closed
    piratetorrents.nuview history2010-04-15 18:00:28Closed
    pisexy.orgview history2010-04-15 17:56:16Closed
    polishbytes.netview history2010-04-15 17:57:00Open
    polishtracker.orgview history2010-04-15 18:05:34Closed
    pornbay.orgview history2010-04-15 18:09:11Open
    PotUKview history2010-04-15 17:37:21Closed
    powerscene.orgview history2010-04-15 18:14:14Closed
    pretome.netview history2010-04-15 17:40:44Closed
    proaudiotorrents.orgview history2010-04-15 18:03:17Closed
    psytorrents.infoview history2010-04-15 17:49:54Closed
    ptfiles.orgview history2010-04-15 18:03:49Closed
    punkhc.dyndns.orgview history2010-04-15 17:56:12Closed
    puretna.comview history2010-04-15 17:40:53Open
    pussytorrents.orgview history2010-04-15 18:05:34Open
    rapthe.netview history2010-04-15 18:21:22Closed
    rarbg.comview history2010-04-15 18:04:33Open
    reload-paradise.netview history2010-04-15 18:05:55Closed
    revolutiontt.netview history2010-04-15 18:21:55Closed
    rmvbustersview history2010-04-15 18:00:23Open
    rmvbusters.plview history2010-04-15 18:03:09Open
    scaliwags.orgview history2010-04-15 18:09:42Closed
    scene-gold.infoview history2010-04-15 17:37:27Offline
    scene-inspired.comview history2010-04-15 18:03:18Open
    sceneaccess.orgview history2010-04-15 17:40:44Closed
    scenebytes.clview history2010-04-15 17:38:10Closed
    scenehd.orgview history2010-04-15 17:45:03Closed
    sceneleech.orgview history2010-04-15 17:57:00Closed
    SceneLife (ScL)view history2010-04-15 18:23:43Closed
    scenetorrents.orgview history2010-04-15 18:23:44Closed
    scenetuga.orgview history2010-04-15 18:09:37Closed
    sciencehd.netview history2010-04-15 17:53:14Closed
    scifitorrents.netview history2010-04-15 17:45:16Offline
    secret-cinema.netview history2010-04-15 18:09:44Closed
    seductiongr.comview history2010-04-15 18:22:20Closed
    seedgames.orgview history2010-04-15 18:10:01Open
    seedmore.orgview history2010-04-15 17:49:07Closed
    sendthatshit.orgview history2010-04-15 18:23:44Open
    sharetorrents.plview history2010-04-15 17:34:13Closed
    sharing-torrents.comview history2010-04-15 18:21:18Closed
    slosoul.netview history2010-04-15 17:35:19Closed
    snowtigers.netview history2010-04-15 17:49:49Closed
    softmp3.orgview history2010-04-15 18:14:44Closed
    softmupparna.netview history2010-04-15 18:09:11Closed
    sounddamage.comview history2010-04-15 18:09:25Closed
    spanishtracker.comview history2010-04-15 17:37:27Open
    spank-d-monkey.comview history2010-04-15 18:24:23Closed
    special.pwtorrents.netview history2010-04-15 18:17:19Closed
    speed.cdview history2010-04-15 17:53:17Closed
    spiryt.ath.cxview history2010-04-15 17:49:49Closed
    sport-scene.netview history2010-04-15 18:17:19Closed
    sportbit.orgview history2010-04-15 18:09:09Closed
    sportleech.netview history2010-04-15 17:40:48Closed
    stmusic.orgview history2010-04-15 18:09:23Open
    supertorrents.orgview history2010-04-15 17:57:00Open
    swebits.orgview history2010-04-15 17:49:54Closed
    sweninjaz.orgview history2010-04-15 18:21:15Closed
    swep2p.orgview history2010-04-15 17:37:25Closed
    swepiracy.orgview history2010-04-15 18:24:22Closed
    swetorrents.no-ip.orgview history2010-04-15 17:35:10Closed
    taiphimhd.comview history2010-04-15 17:40:49Open
    tastetherainbow.wsview history2010-04-15 17:56:13Closed
    teamofgreekz.comview history2010-04-15 18:23:46Closed
    tehconnection.euview history2010-04-15 18:06:22Closed
    the-zomb.comview history2010-04-15 17:38:13Open
    thebox.bzview history2010-04-15 18:09:44Open
    thedvdclub.orgview history2010-04-15 17:49:50Open
    thegt.netview history2010-04-15 18:00:20Closed
    themixingbowl.orgview history2010-04-15 17:38:10Closed
    theoccult.bzview history2010-04-15 17:56:12Closed
    thepeerhub.comview history2010-04-15 18:24:16Open
    theplace.bzview history2010-04-15 18:09:17Closed
    thepokerbay.orgview history2010-04-15 17:36:33Open
    thevault.bzview history2010-04-15 18:14:45Closed
    titaniumtorrents.netview history2010-04-15 17:45:48Offline
    tmtorrents.orgview history2010-04-15 18:00:21Closed
    topbytes.netview history2010-04-15 17:37:17Closed
    topbytes.netview history2010-04-15 18:14:15Closed
    tophos.orgview history2010-04-15 18:24:22Closed
    torrent-damage.netview history2010-04-15 18:22:22Closed
    torrent.itview history2010-04-15 18:24:16Closed
    torrent411.comview history2010-04-15 17:45:12Open
    torrentbits.roview history2010-04-15 17:37:20Closed
    torrentbully.comview history2010-04-15 18:17:15Closed
    torrentdownloads.netview history2010-04-15 18:05:55Open
    torrentgaming.netview history2010-04-15 18:24:19Closed
    torrentgeeks.comview history2010-04-15 18:17:20Offline
    torrenthr.orgview history2010-04-15 18:24:16Open
    torrentkings.orgview history2010-04-15 17:53:09Closed
    torrentleech.orgview history2010-04-15 18:22:46Closed
    torrentseed.orgview history2010-04-15 17:35:15Closed
    torrentsforall.netview history2010-04-15 17:45:47Open
    torrentsmd.comview history2010-04-15 18:00:20Open
    torrentvault.orgview history2010-04-15 17:40:51Closed
    torrentzilla.orgview history2010-04-15 18:24:11Open
    torrentzone.netview history2010-04-15 17:45:04Open
    totaltorrents.comview history2010-04-15 17:37:31Closed
    trancebits.comview history2010-04-15 18:05:34Closed
    trancebooster.netview history2010-04-15 17:56:11Closed
    trancetraffic.comview history2010-04-15 17:37:18Closed
    tri-tavern.comview history2010-04-15 18:23:19Closed
    tribalmixes.comview history2010-04-15 18:20:39Open
    tugaleech.comview history2010-04-15 18:24:25Closed
    tunebully.comview history2010-04-15 17:49:08Closed
    tv.torrents.roview history2010-04-15 17:35:11Closed
    tvtorrents.comview history2010-04-15 17:38:02Open
    ugstorrents.comview history2010-04-15 18:09:15Closed
    uknova.comview history2010-04-15 18:14:15Closed
    underground-gamer.comview history2010-04-15 17:49:06Open
    victorrent.netview history2010-04-15 17:45:14Closed
    vortexnetwork.orgview history2010-04-15 17:53:16Offline
    waffles.fmview history2010-04-15 17:53:12Closed
    wantedfiles.roview history2010-04-15 17:49:07Open
    warezbros.orgview history2010-04-15 18:03:20Closed
    what.cdview history2010-04-15 17:53:12Closed
    wild-bytes.orgview history2010-04-15 18:00:27Closed
    wolfbits.orgview history2010-04-15 18:14:09Closed
    worldboxingvideoarchive.comview history2010-04-15 18:09:10Open
    www.bt-pt.netview history2010-04-15 18:09:45Closed
    www.llywot.comview history2010-04-15 17:53:13Closed
    xbitz.orgview history2010-04-15 18:21:21Open
    xider.huview history2010-04-15 18:05:34Open
    xtremespeeds.netview history2010-04-15 18:04:33Closed
    xtremewrestlingtorrents.netview history2010-04-15 18:00:27Open
    xtremezone.roview history2010-04-15 18:14:43Closed
    yuwabits.netview history2010-04-15 17:45:17Open
    zanettetorrent.comview history2010-04-15 18:17:12Closed
    zinebytes.orgview history2010-04-15 17:34:18Closed
    +
    +


    + + +
    + + + + + + diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/01-basic.js b/node_modules/jsdom/node_modules/htmlparser/tests/01-basic.js new file mode 100644 index 0000000..7846898 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/01-basic.js @@ -0,0 +1,61 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Basic test"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = "The TitleHello world"; +exports.expected = + [ { raw: 'html' + , data: 'html' + , type: 'tag' + , name: 'html' + , children: + [ { raw: 'title' + , data: 'title' + , type: 'tag' + , name: 'title' + , children: [ { raw: 'The Title', data: 'The Title', type: 'text' } ] + } + , { raw: 'body' + , data: 'body' + , type: 'tag' + , name: 'body' + , children: + [ { raw: 'Hello world' + , data: 'Hello world' + , type: 'text' + } + ] + } + ] + } + ]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/02-single_tag_1.js b/node_modules/jsdom/node_modules/htmlparser/tests/02-single_tag_1.js new file mode 100644 index 0000000..1735b5e --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/02-single_tag_1.js @@ -0,0 +1,39 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Single Tag 1"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = "
    text
    "; +exports.expected = + [ { raw: 'br', data: 'br', type: 'tag', name: 'br' } + , { raw: 'text', data: 'text', type: 'text' } + ]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/03-single_tag_2.js b/node_modules/jsdom/node_modules/htmlparser/tests/03-single_tag_2.js new file mode 100644 index 0000000..2e6e92c --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/03-single_tag_2.js @@ -0,0 +1,40 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Single Tag 2"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = "
    text
    "; +exports.expected = + [ { raw: 'br', data: 'br', type: 'tag', name: 'br' } + , { raw: 'text', data: 'text', type: 'text' } + , { raw: 'br', data: 'br', type: 'tag', name: 'br' } + ]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/04-unescaped_in_script.js b/node_modules/jsdom/node_modules/htmlparser/tests/04-unescaped_in_script.js new file mode 100644 index 0000000..fb2cc3a --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/04-unescaped_in_script.js @@ -0,0 +1,56 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Unescaped chars in script"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = ""; +exports.expected = +[ { raw: 'head' + , data: 'head' + , type: 'tag' + , name: 'head' + , children: + [ { raw: 'script language="Javascript"' + , data: 'script language="Javascript"' + , type: 'script' + , name: 'script' + , attribs: { language: 'Javascript' } + , children: + [ { raw: 'var foo = ""; alert(2 > foo); var baz = 10 << 2; var zip = 10 >> 1; var yap = \"<<>>>><<\";' + , data: 'var foo = ""; alert(2 > foo); var baz = 10 << 2; var zip = 10 >> 1; var yap = \"<<>>>><<\";' + , type: 'text' + } + ] + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/05-tags_in_comment.js b/node_modules/jsdom/node_modules/htmlparser/tests/05-tags_in_comment.js new file mode 100644 index 0000000..68a0779 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/05-tags_in_comment.js @@ -0,0 +1,48 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Special char in comment"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = ""; +exports.expected = +[ { raw: 'head' + , data: 'head' + , type: 'tag' + , name: 'head' + , children: + [ { raw: ' commented out tags Test' + , data: ' commented out tags Test' + , type: 'comment' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/06-comment_in_script.js b/node_modules/jsdom/node_modules/htmlparser/tests/06-comment_in_script.js new file mode 100644 index 0000000..2d04ec0 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/06-comment_in_script.js @@ -0,0 +1,48 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Script source in comment"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = ""; +exports.expected = +[ { raw: 'script' + , data: 'script' + , type: 'script' + , name: 'script' + , children: + [ { raw: 'var foo = 1;' + , data: 'var foo = 1;' + , type: 'comment' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/07-unescaped_in_style.js b/node_modules/jsdom/node_modules/htmlparser/tests/07-unescaped_in_style.js new file mode 100644 index 0000000..563a64a --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/07-unescaped_in_style.js @@ -0,0 +1,49 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Unescaped chars in style"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = ""; +exports.expected = +[ { raw: 'style type="text/css"' + , data: 'style type="text/css"' + , type: 'style' + , name: 'style' + , attribs: { type: 'text/css' } + , children: + [ { raw: '\n body > p\n { font-weight: bold; }' + , data: '\n body > p\n { font-weight: bold; }' + , type: 'text' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/08-extra_spaces_in_tag.js b/node_modules/jsdom/node_modules/htmlparser/tests/08-extra_spaces_in_tag.js new file mode 100644 index 0000000..1767565 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/08-extra_spaces_in_tag.js @@ -0,0 +1,49 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Extra spaces in tag"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = "<\n font \n size='14' \n>the text<\n / \nfont \n>"; +exports.expected = +[ { raw: '\n font \n size=\'14\' \n' + , data: 'font \n size=\'14\'' + , type: 'tag' + , name: 'font' + , attribs: { size: '14' } + , children: + [ { raw: 'the text' + , data: 'the text' + , type: 'text' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/09-unquoted_attrib.js b/node_modules/jsdom/node_modules/htmlparser/tests/09-unquoted_attrib.js new file mode 100644 index 0000000..da6bac7 --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/09-unquoted_attrib.js @@ -0,0 +1,49 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Unquoted attributes"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = "the text"; +exports.expected = +[ { raw: 'font size= 14' + , data: 'font size= 14' + , type: 'tag' + , name: 'font' + , attribs: { size: '14' } + , children: + [ { raw: 'the text' + , data: 'the text' + , type: 'text' + } + ] + } +]; + +})(); diff --git a/node_modules/jsdom/node_modules/htmlparser/tests/10-singular_attribute.js b/node_modules/jsdom/node_modules/htmlparser/tests/10-singular_attribute.js new file mode 100644 index 0000000..6c22e1a --- /dev/null +++ b/node_modules/jsdom/node_modules/htmlparser/tests/10-singular_attribute.js @@ -0,0 +1,43 @@ +(function () { + +function RunningInNode () { + return( + (typeof require) == "function" + && + (typeof exports) == "object" + && + (typeof module) == "object" + && + (typeof __filename) == "string" + && + (typeof __dirname) == "string" + ); +} + +if (!RunningInNode()) { + if (!this.Tautologistics) + this.Tautologistics = {}; + if (!this.Tautologistics.NodeHtmlParser) + this.Tautologistics.NodeHtmlParser = {}; + if (!this.Tautologistics.NodeHtmlParser.Tests) + this.Tautologistics.NodeHtmlParser.Tests = []; + exports = {}; + this.Tautologistics.NodeHtmlParser.Tests.push(exports); +} + +exports.name = "Singular attribute"; +exports.options = { + handler: {} + , parser: {} +}; +exports.html = "
    etc. + break; + tokenizer = tag_open_state; + break; + case 0x0000: // NULL + // Usually null characters emitted by the tokenizer will be + // ignored by the tree builder, but sometimes they'll be + // converted to \uFFFD. I don't want to have the search every + // string emitted to replace NULs, so I'll set a flag + // if I've emitted a NUL. + push(textrun,c); + textIncludesNUL = true; + break; + case EOF: + emitEOF(); + break; + default: + // Instead of just pushing a single character and then + // coming back to the very same place, lookahead and + // emit everything we can at once. + emitCharsWhile(DATATEXT) || push(textrun, c); + break; + } + } + + function character_reference_in_data_state(c, lookahead, eof) { + var char = parseCharRef(lookahead, false); + if (char !== null) { + if (typeof char === "number") push(textrun,char); + else pushAll(textrun, char); // An array of characters + } + else + push(textrun,0x0026); // AMPERSAND; + + tokenizer = data_state; + } + character_reference_in_data_state.lookahead = CHARREF; + + function rcdata_state(c) { + // Save the open tag so we can find a matching close tag + switch(c) { + case 0x0026: // AMPERSAND + tokenizer = character_reference_in_rcdata_state; + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = rcdata_less_than_sign_state; + break; + case 0x0000: // NULL + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + textIncludesNUL = true; + break; + case EOF: + emitEOF(); + break; + default: + push(textrun,c); + break; + } + } + + function character_reference_in_rcdata_state(c, lookahead, eof) { + var char = parseCharRef(lookahead, false); + if (char !== null) { + if (typeof char === "number") push(textrun,char); + else pushAll(textrun, char); // An array of characters + } + else + push(textrun,0x0026); // AMPERSAND; + + tokenizer = rcdata_state; + } + character_reference_in_rcdata_state.lookahead = CHARREF; + + function rawtext_state(c) { + switch(c) { + case 0x003C: // LESS-THAN SIGN + tokenizer = rawtext_less_than_sign_state; + break; + case 0x0000: // NULL + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + emitEOF(); + break; + default: + emitCharsWhile(RAWTEXT) || push(textrun, c); + break; + } + } + + function script_data_state(c) { + switch(c) { + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_less_than_sign_state; + break; + case 0x0000: // NULL + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + emitEOF(); + break; + default: + emitCharsWhile(RAWTEXT) || push(textrun, c); + break; + } + } + + function plaintext_state(c) { + switch(c) { + case 0x0000: // NULL + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + emitEOF(); + break; + default: + emitCharsWhile(PLAINTEXT) || push(textrun, c); + break; + } + } + + function tag_open_state(c) { + switch(c) { + case 0x0021: // EXCLAMATION MARK + tokenizer = markup_declaration_open_state; + break; + case 0x002F: // SOLIDUS + tokenizer = end_tag_open_state; + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + c += 0x20; // to lowercase + /* falls through */ + + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginTagName(); + appendChar(tagnamebuf, c); + tokenizer = tag_name_state; + break; + case 0x003F: // QUESTION MARK + nextchar--; // pushback + tokenizer = bogus_comment_state; + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + nextchar--; // pushback + tokenizer = data_state; + break; + } + } + + function end_tag_open_state(c) { + switch(c) { + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + c += 0x20; // to lowercase + /* falls through */ + + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginEndTagName(); + appendChar(tagnamebuf, c); + tokenizer = tag_name_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + break; + case EOF: + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + nextchar--; // pushback + tokenizer = data_state; + break; + default: + nextchar--; // pushback + tokenizer = bogus_comment_state; + break; + } + } + + function tag_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = before_attribute_name_state; + break; + case 0x002F: // SOLIDUS + tokenizer = self_closing_start_tag_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitTag(); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(tagnamebuf, c + 0x0020); + break; + case 0x0000: // NULL + appendChar(tagnamebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(tagnamebuf, c); + // appendCharsWhile(tagnamebuf, TAGNAMECHARS) || appendChar(tagnamebuf, c); + break; + } + } + + function rcdata_less_than_sign_state(c) { + /* identical to the RAWTEXT less-than sign state, except s/RAWTEXT/RCDATA/g */ + if (c === 0x002F) { // SOLIDUS + beginTempBuf(); + tokenizer = rcdata_end_tag_open_state; + } + else { + push(textrun,0x003C); // LESS-THAN SIGN + nextchar--; // pushback + tokenizer = rcdata_state; + } + } + + function rcdata_end_tag_open_state(c) { + /* identical to the RAWTEXT (and Script data) end tag open state, except s/RAWTEXT/RCDATA/g */ + switch(c) { + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginEndTagName(); + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + tokenizer = rcdata_end_tag_name_state; + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginEndTagName(); + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + tokenizer = rcdata_end_tag_name_state; + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + nextchar--; // pushback + tokenizer = rcdata_state; + break; + } + } + + function rcdata_end_tag_name_state(c) { + /* identical to the RAWTEXT (and Script data) end tag name state, except s/RAWTEXT/RCDATA/g */ + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + if (appropriateEndTag(tagnamebuf)) { + tokenizer = before_attribute_name_state; + return; + } + break; + case 0x002F: // SOLIDUS + if (appropriateEndTag(tagnamebuf)) { + tokenizer = self_closing_start_tag_state; + return; + } + break; + case 0x003E: // GREATER-THAN SIGN + if (appropriateEndTag(tagnamebuf)) { + tokenizer = data_state; + emitTag(); + return; + } + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + return; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + return; + default: + break; + } + + // If we don't return in one of the cases above, then this was not + // an appropriately matching close tag, so back out by emitting all + // the characters as text + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + pushAll(textrun, tempbuf); + nextchar--; // pushback + tokenizer = rcdata_state; + } + + function rawtext_less_than_sign_state(c) { + /* identical to the RCDATA less-than sign state, except s/RCDATA/RAWTEXT/g + */ + if (c === 0x002F) { // SOLIDUS + beginTempBuf(); + tokenizer = rawtext_end_tag_open_state; + } + else { + push(textrun,0x003C); // LESS-THAN SIGN + nextchar--; // pushback + tokenizer = rawtext_state; + } + } + + function rawtext_end_tag_open_state(c) { + /* identical to the RCDATA (and Script data) end tag open state, except s/RCDATA/RAWTEXT/g */ + switch(c) { + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginEndTagName(); + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + tokenizer = rawtext_end_tag_name_state; + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginEndTagName(); + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + tokenizer = rawtext_end_tag_name_state; + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + nextchar--; // pushback + tokenizer = rawtext_state; + break; + } + } + + function rawtext_end_tag_name_state(c) { + /* identical to the RCDATA (and Script data) end tag name state, except s/RCDATA/RAWTEXT/g */ + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + if (appropriateEndTag(tagnamebuf)) { + tokenizer = before_attribute_name_state; + return; + } + break; + case 0x002F: // SOLIDUS + if (appropriateEndTag(tagnamebuf)) { + tokenizer = self_closing_start_tag_state; + return; + } + break; + case 0x003E: // GREATER-THAN SIGN + if (appropriateEndTag(tagnamebuf)) { + tokenizer = data_state; + emitTag(); + return; + } + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + return; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + return; + default: + break; + } + + // If we don't return in one of the cases above, then this was not + // an appropriately matching close tag, so back out by emitting all + // the characters as text + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + pushAll(textrun,tempbuf); + nextchar--; // pushback + tokenizer = rawtext_state; + } + + function script_data_less_than_sign_state(c) { + switch(c) { + case 0x002F: // SOLIDUS + beginTempBuf(); + tokenizer = script_data_end_tag_open_state; + break; + case 0x0021: // EXCLAMATION MARK + tokenizer = script_data_escape_start_state; + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x0021); // EXCLAMATION MARK + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + nextchar--; // pushback + tokenizer = script_data_state; + break; + } + } + + function script_data_end_tag_open_state(c) { + /* identical to the RCDATA (and RAWTEXT) end tag open state, except s/RCDATA/Script data/g */ + switch(c) { + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginEndTagName(); + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + tokenizer = script_data_end_tag_name_state; + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginEndTagName(); + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + tokenizer = script_data_end_tag_name_state; + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + nextchar--; // pushback + tokenizer = script_data_state; + break; + } + } + + function script_data_end_tag_name_state(c) { + /* identical to the RCDATA (and RAWTEXT) end tag name state, except s/RCDATA/Script data/g */ + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + if (appropriateEndTag(tagnamebuf)) { + tokenizer = before_attribute_name_state; + return; + } + break; + case 0x002F: // SOLIDUS + if (appropriateEndTag(tagnamebuf)) { + tokenizer = self_closing_start_tag_state; + return; + } + break; + case 0x003E: // GREATER-THAN SIGN + if (appropriateEndTag(tagnamebuf)) { + tokenizer = data_state; + emitTag(); + return; + } + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + return; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + return; + default: + break; + } + + // If we don't return in one of the cases above, then this was not + // an appropriately matching close tag, so back out by emitting all + // the characters as text + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + pushAll(textrun,tempbuf); + nextchar--; // pushback + tokenizer = script_data_state; + } + + function script_data_escape_start_state(c) { + if (c === 0x002D) { // HYPHEN-MINUS + tokenizer = script_data_escape_start_dash_state; + push(textrun,0x002D); // HYPHEN-MINUS + } + else { + nextchar--; // pushback + tokenizer = script_data_state; + } + } + + function script_data_escape_start_dash_state(c) { + if (c === 0x002D) { // HYPHEN-MINUS + tokenizer = script_data_escaped_dash_dash_state; + push(textrun,0x002D); // HYPHEN-MINUS + } + else { + nextchar--; // pushback + tokenizer = script_data_state; + } + } + + function script_data_escaped_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = script_data_escaped_dash_state; + push(textrun,0x002D); // HYPHEN-MINUS + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_escaped_less_than_sign_state; + break; + case 0x0000: // NULL + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + push(textrun,c); + break; + } + } + + function script_data_escaped_dash_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = script_data_escaped_dash_dash_state; + push(textrun,0x002D); // HYPHEN-MINUS + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_escaped_less_than_sign_state; + break; + case 0x0000: // NULL + tokenizer = script_data_escaped_state; + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + tokenizer = script_data_escaped_state; + push(textrun,c); + break; + } + } + + function script_data_escaped_dash_dash_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + push(textrun,0x002D); // HYPHEN-MINUS + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_escaped_less_than_sign_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = script_data_state; + push(textrun,0x003E); // GREATER-THAN SIGN + break; + case 0x0000: // NULL + tokenizer = script_data_escaped_state; + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + tokenizer = script_data_escaped_state; + push(textrun,c); + break; + } + } + + function script_data_escaped_less_than_sign_state(c) { + switch(c) { + case 0x002F: // SOLIDUS + beginTempBuf(); + tokenizer = script_data_escaped_end_tag_open_state; + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginTempBuf(); + appendChar(tempbuf, c + 0x0020); + tokenizer = script_data_double_escape_start_state; + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,c); + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginTempBuf(); + appendChar(tempbuf, c); + tokenizer = script_data_double_escape_start_state; + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,c); + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + nextchar--; // pushback + tokenizer = script_data_escaped_state; + break; + } + } + + function script_data_escaped_end_tag_open_state(c) { + switch(c) { + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginEndTagName(); + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + tokenizer = script_data_escaped_end_tag_name_state; + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + beginEndTagName(); + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + tokenizer = script_data_escaped_end_tag_name_state; + break; + default: + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + nextchar--; // pushback + tokenizer = script_data_escaped_state; + break; + } + } + + function script_data_escaped_end_tag_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + if (appropriateEndTag(tagnamebuf)) { + tokenizer = before_attribute_name_state; + return; + } + break; + case 0x002F: // SOLIDUS + if (appropriateEndTag(tagnamebuf)) { + tokenizer = self_closing_start_tag_state; + return; + } + break; + case 0x003E: // GREATER-THAN SIGN + if (appropriateEndTag(tagnamebuf)) { + tokenizer = data_state; + emitTag(); + return; + } + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(tagnamebuf, c + 0x0020); + appendChar(tempbuf, c); + return; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + appendChar(tagnamebuf, c); + appendChar(tempbuf, c); + return; + default: + break; + } + + // We get here in the default case, and if the closing tagname + // is not an appropriate tagname. + push(textrun,0x003C); // LESS-THAN SIGN + push(textrun,0x002F); // SOLIDUS + pushAll(textrun,tempbuf); + nextchar--; // pushback + tokenizer = script_data_escaped_state; + } + + function script_data_double_escape_start_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + case 0x002F: // SOLIDUS + case 0x003E: // GREATER-THAN SIGN + if (buf2str(tempbuf) === "script") { + tokenizer = script_data_double_escaped_state; + } + else { + tokenizer = script_data_escaped_state; + } + push(textrun,c); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(tempbuf, c + 0x0020); + push(textrun,c); + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + appendChar(tempbuf, c); + push(textrun,c); + break; + default: + nextchar--; // pushback + tokenizer = script_data_escaped_state; + break; + } + } + + function script_data_double_escaped_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = script_data_double_escaped_dash_state; + push(textrun,0x002D); // HYPHEN-MINUS + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_double_escaped_less_than_sign_state; + push(textrun,0x003C); // LESS-THAN SIGN + break; + case 0x0000: // NULL + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + push(textrun,c); + break; + } + } + + function script_data_double_escaped_dash_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = script_data_double_escaped_dash_dash_state; + push(textrun,0x002D); // HYPHEN-MINUS + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_double_escaped_less_than_sign_state; + push(textrun,0x003C); // LESS-THAN SIGN + break; + case 0x0000: // NULL + tokenizer = script_data_double_escaped_state; + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + tokenizer = script_data_double_escaped_state; + push(textrun,c); + break; + } + } + + function script_data_double_escaped_dash_dash_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + push(textrun,0x002D); // HYPHEN-MINUS + break; + case 0x003C: // LESS-THAN SIGN + tokenizer = script_data_double_escaped_less_than_sign_state; + push(textrun,0x003C); // LESS-THAN SIGN + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = script_data_state; + push(textrun,0x003E); // GREATER-THAN SIGN + break; + case 0x0000: // NULL + tokenizer = script_data_double_escaped_state; + push(textrun,0xFFFD); // REPLACEMENT CHARACTER + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + tokenizer = script_data_double_escaped_state; + push(textrun,c); + break; + } + } + + function script_data_double_escaped_less_than_sign_state(c) { + if (c === 0x002F) { // SOLIDUS + beginTempBuf(); + tokenizer = script_data_double_escape_end_state; + push(textrun,0x002F); // SOLIDUS + } + else { + nextchar--; // pushback + tokenizer = script_data_double_escaped_state; + } + } + + function script_data_double_escape_end_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + case 0x002F: // SOLIDUS + case 0x003E: // GREATER-THAN SIGN + if (buf2str(tempbuf) === "script") { + tokenizer = script_data_escaped_state; + } + else { + tokenizer = script_data_double_escaped_state; + } + push(textrun,c); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(tempbuf, c + 0x0020); + push(textrun,c); + break; + case 0x0061: // [a-z] + case 0x0062:case 0x0063:case 0x0064:case 0x0065:case 0x0066: + case 0x0067:case 0x0068:case 0x0069:case 0x006A:case 0x006B: + case 0x006C:case 0x006D:case 0x006E:case 0x006F:case 0x0070: + case 0x0071:case 0x0072:case 0x0073:case 0x0074:case 0x0075: + case 0x0076:case 0x0077:case 0x0078:case 0x0079:case 0x007A: + appendChar(tempbuf, c); + push(textrun,c); + break; + default: + nextchar--; // pushback + tokenizer = script_data_double_escaped_state; + break; + } + } + + function before_attribute_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + break; + case 0x002F: // SOLIDUS + tokenizer = self_closing_start_tag_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitTag(); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginAttrName(); + appendChar(attrnamebuf, c + 0x0020); + tokenizer = attribute_name_state; + break; + case 0x0000: // NULL + beginAttrName(); + appendChar(attrnamebuf, 0xFFFD); + tokenizer = attribute_name_state; + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + case 0x0022: // QUOTATION MARK + case 0x0027: // APOSTROPHE + case 0x003C: // LESS-THAN SIGN + case 0x003D: // EQUALS SIGN + /* falls through */ + default: + if (handleSimpleAttribute()) break; + beginAttrName(); + appendChar(attrnamebuf, c); + tokenizer = attribute_name_state; + break; + } + } + + function attribute_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = after_attribute_name_state; + break; + case 0x002F: // SOLIDUS + addAttribute(attrnamebuf); + tokenizer = self_closing_start_tag_state; + break; + case 0x003D: // EQUALS SIGN + beginAttrValue(); + tokenizer = before_attribute_value_state; + break; + case 0x003E: // GREATER-THAN SIGN + addAttribute(attrnamebuf); + tokenizer = data_state; + emitTag(); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(attrnamebuf, c + 0x0020); + break; + case 0x0000: // NULL + appendChar(attrnamebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + case 0x0022: // QUOTATION MARK + case 0x0027: // APOSTROPHE + case 0x003C: // LESS-THAN SIGN + /* falls through */ + default: + appendChar(attrnamebuf, c); + break; + } + } + + function after_attribute_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + break; + case 0x002F: // SOLIDUS + addAttribute(attrnamebuf); + tokenizer = self_closing_start_tag_state; + break; + case 0x003D: // EQUALS SIGN + beginAttrValue(); + tokenizer = before_attribute_value_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + addAttribute(attrnamebuf); + emitTag(); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + addAttribute(attrnamebuf); + beginAttrName(); + appendChar(attrnamebuf, c + 0x0020); + tokenizer = attribute_name_state; + break; + case 0x0000: // NULL + addAttribute(attrnamebuf); + beginAttrName(); + appendChar(attrnamebuf, 0xFFFD); + tokenizer = attribute_name_state; + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + case 0x0022: // QUOTATION MARK + case 0x0027: // APOSTROPHE + case 0x003C: // LESS-THAN SIGN + /* falls through */ + default: + addAttribute(attrnamebuf); + beginAttrName(); + appendChar(attrnamebuf, c); + tokenizer = attribute_name_state; + break; + } + } + + function before_attribute_value_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + break; + case 0x0022: // QUOTATION MARK + tokenizer = attribute_value_double_quoted_state; + break; + case 0x0026: // AMPERSAND + nextchar--; // pushback + tokenizer = attribute_value_unquoted_state; + break; + case 0x0027: // APOSTROPHE + tokenizer = attribute_value_single_quoted_state; + break; + case 0x0000: // NULL + appendChar(attrvaluebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + tokenizer = attribute_value_unquoted_state; + break; + case 0x003E: // GREATER-THAN SIGN + addAttribute(attrnamebuf); + emitTag(); + tokenizer = data_state; + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + case 0x003C: // LESS-THAN SIGN + case 0x003D: // EQUALS SIGN + case 0x0060: // GRAVE ACCENT + /* falls through */ + default: + appendChar(attrvaluebuf, c); + tokenizer = attribute_value_unquoted_state; + break; + } + } + + function attribute_value_double_quoted_state(c) { + switch(c) { + case 0x0022: // QUOTATION MARK + addAttribute(attrnamebuf, attrvaluebuf); + tokenizer = after_attribute_value_quoted_state; + break; + case 0x0026: // AMPERSAND + pushState(); + tokenizer = character_reference_in_attribute_value_state; + break; + case 0x0000: // NULL + appendChar(attrvaluebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(attrvaluebuf, c); + // appendCharsWhile(attrvaluebuf, DBLQUOTEATTRVAL); + break; + } + } + + function attribute_value_single_quoted_state(c) { + switch(c) { + case 0x0027: // APOSTROPHE + addAttribute(attrnamebuf, attrvaluebuf); + tokenizer = after_attribute_value_quoted_state; + break; + case 0x0026: // AMPERSAND + pushState(); + tokenizer = character_reference_in_attribute_value_state; + break; + case 0x0000: // NULL + appendChar(attrvaluebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(attrvaluebuf, c); + // appendCharsWhile(attrvaluebuf, SINGLEQUOTEATTRVAL); + break; + } + } + + function attribute_value_unquoted_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + addAttribute(attrnamebuf, attrvaluebuf); + tokenizer = before_attribute_name_state; + break; + case 0x0026: // AMPERSAND + pushState(); + tokenizer = character_reference_in_attribute_value_state; + break; + case 0x003E: // GREATER-THAN SIGN + addAttribute(attrnamebuf, attrvaluebuf); + tokenizer = data_state; + emitTag(); + break; + case 0x0000: // NULL + appendChar(attrvaluebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + case 0x0022: // QUOTATION MARK + case 0x0027: // APOSTROPHE + case 0x003C: // LESS-THAN SIGN + case 0x003D: // EQUALS SIGN + case 0x0060: // GRAVE ACCENT + /* falls through */ + default: + appendChar(attrvaluebuf, c); + // appendCharsWhile(attrvaluebuf, UNQUOTEDATTRVAL); + break; + } + } + + function character_reference_in_attribute_value_state(c, lookahead, eof) { + var char = parseCharRef(lookahead, true); + if (char !== null) { + if (typeof char === "number") + appendChar(attrvaluebuf, char); + else { + // An array of numbers + for(var i = 0; i < char.length; i++) { + appendChar(attrvaluebuf, char[i]); + } + } + } + else { + appendChar(attrvaluebuf, 0x0026); // AMPERSAND; + } + + popState(); + } + character_reference_in_attribute_value_state.lookahead = ATTRCHARREF; + + function after_attribute_value_quoted_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = before_attribute_name_state; + break; + case 0x002F: // SOLIDUS + tokenizer = self_closing_start_tag_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitTag(); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + nextchar--; // pushback + tokenizer = before_attribute_name_state; + break; + } + } + + function self_closing_start_tag_state(c) { + switch(c) { + case 0x003E: // GREATER-THAN SIGN + // Set the self-closing flag of the current tag token. + tokenizer = data_state; + emitSelfClosingTag(true); + break; + case EOF: + nextchar--; // pushback + tokenizer = data_state; + break; + default: + nextchar--; // pushback + tokenizer = before_attribute_name_state; + break; + } + } + + function bogus_comment_state(c, lookahead, eof) { + var len = lookahead.length; + + if (eof) { + nextchar += len-1; // don't consume the eof + } + else { + nextchar += len; + } + + var comment = substring(lookahead, 0, len-1); + + comment = replace(comment, /\u0000/g,"\uFFFD"); + comment = replace(comment, /\u000D\u000A/g,"\u000A"); + comment = replace(comment, /\u000D/g,"\u000A"); + + insertToken(COMMENT, comment); + tokenizer = data_state; + } + bogus_comment_state.lookahead = ">"; + + function markup_declaration_open_state(c, lookahead, eof) { + if (lookahead[0] === "-" && lookahead[1] === "-") { + nextchar += 2; + beginComment(); + tokenizer = comment_start_state; + return; + } + + if (toUpperCase(lookahead) === "DOCTYPE") { + nextchar += 7; + tokenizer = doctype_state; + } + else if (lookahead === "[CDATA[" && cdataAllowed()) { + nextchar += 7; + tokenizer = cdata_section_state; + } + else { + tokenizer = bogus_comment_state; + } + } + markup_declaration_open_state.lookahead = 7; + + function comment_start_state(c) { + beginComment(); + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = comment_start_dash_state; + break; + case 0x0000: // NULL + appendChar(commentbuf, 0xFFFD /* REPLACEMENT CHARACTER */); + tokenizer = comment_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + insertToken(COMMENT, buf2str(commentbuf)); + break; /* see comment in comment end state */ + case EOF: + insertToken(COMMENT, buf2str(commentbuf)); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(commentbuf, c); + tokenizer = comment_state; + break; + } + } + + function comment_start_dash_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = comment_end_state; + break; + case 0x0000: // NULL + appendChar(commentbuf, 0x002D /* HYPHEN-MINUS */); + appendChar(commentbuf, 0xFFFD); + tokenizer = comment_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + insertToken(COMMENT, buf2str(commentbuf)); + break; + case EOF: + insertToken(COMMENT, buf2str(commentbuf)); + nextchar--; // pushback + tokenizer = data_state; + break; /* see comment in comment end state */ + default: + appendChar(commentbuf, 0x002D /* HYPHEN-MINUS */); + appendChar(commentbuf, c); + tokenizer = comment_state; + break; + } + } + + function comment_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = comment_end_dash_state; + break; + case 0x0000: // NULL + appendChar(commentbuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + insertToken(COMMENT, buf2str(commentbuf)); + nextchar--; // pushback + tokenizer = data_state; + break; /* see comment in comment end state */ + default: + appendChar(commentbuf, c); + break; + } + } + + function comment_end_dash_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + tokenizer = comment_end_state; + break; + case 0x0000: // NULL + appendChar(commentbuf, 0x002D /* HYPHEN-MINUS */); + appendChar(commentbuf, 0xFFFD); + tokenizer = comment_state; + break; + case EOF: + insertToken(COMMENT, buf2str(commentbuf)); + nextchar--; // pushback + tokenizer = data_state; + break; /* see comment in comment end state */ + default: + appendChar(commentbuf, 0x002D /* HYPHEN-MINUS */); + appendChar(commentbuf, c); + tokenizer = comment_state; + break; + } + } + + function comment_end_state(c) { + switch(c) { + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + insertToken(COMMENT, buf2str(commentbuf)); + break; + case 0x0000: // NULL + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0xFFFD); + tokenizer = comment_state; + break; + case 0x0021: // EXCLAMATION MARK + tokenizer = comment_end_bang_state; + break; + case 0x002D: // HYPHEN-MINUS + appendChar(commentbuf, 0x002D); + break; + case EOF: + insertToken(COMMENT, buf2str(commentbuf)); + nextchar--; // pushback + tokenizer = data_state; + break; /* For security reasons: otherwise, hostile user could put a script in a comment e.g. in a blog comment and then DOS the server so that the end tag isn't read, and then the commented script tag would be treated as live code */ + default: + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, c); + tokenizer = comment_state; + break; + } + } + + function comment_end_bang_state(c) { + switch(c) { + case 0x002D: // HYPHEN-MINUS + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x0021); + tokenizer = comment_end_dash_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + insertToken(COMMENT, buf2str(commentbuf)); + break; + case 0x0000: // NULL + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x0021); + appendChar(commentbuf, 0xFFFD); + tokenizer = comment_state; + break; + case EOF: + insertToken(COMMENT, buf2str(commentbuf)); + nextchar--; // pushback + tokenizer = data_state; + break; /* see comment in comment end state */ + default: + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x002D); + appendChar(commentbuf, 0x0021); + appendChar(commentbuf, c); + tokenizer = comment_state; + break; + } + } + + function doctype_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = before_doctype_name_state; + break; + case EOF: + beginDoctype(); + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + nextchar--; // pushback + tokenizer = before_doctype_name_state; + break; + } + } + + function before_doctype_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + beginDoctype(); + appendChar(doctypenamebuf, c + 0x0020); + tokenizer = doctype_name_state; + break; + case 0x0000: // NULL + beginDoctype(); + appendChar(doctypenamebuf, 0xFFFD); + tokenizer = doctype_name_state; + break; + case 0x003E: // GREATER-THAN SIGN + beginDoctype(); + tokenizer = data_state; + forcequirks(); + emitDoctype(); + break; + case EOF: + beginDoctype(); + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + beginDoctype(); + appendChar(doctypenamebuf, c); + tokenizer = doctype_name_state; + break; + } + } + + function doctype_name_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = after_doctype_name_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitDoctype(); + break; + case 0x0041: // [A-Z] + case 0x0042:case 0x0043:case 0x0044:case 0x0045:case 0x0046: + case 0x0047:case 0x0048:case 0x0049:case 0x004A:case 0x004B: + case 0x004C:case 0x004D:case 0x004E:case 0x004F:case 0x0050: + case 0x0051:case 0x0052:case 0x0053:case 0x0054:case 0x0055: + case 0x0056:case 0x0057:case 0x0058:case 0x0059:case 0x005A: + appendChar(doctypenamebuf, c + 0x0020); + break; + case 0x0000: // NULL + appendChar(doctypenamebuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(doctypenamebuf, c); + break; + } + } + + function after_doctype_name_state(c, lookahead, eof) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + nextchar += 1; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + nextchar += 1; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + tokenizer = data_state; + break; + default: + lookahead = toUpperCase(lookahead); + if (lookahead === "PUBLIC") { + nextchar += 6; + tokenizer = after_doctype_public_keyword_state; + } + else if (lookahead === "SYSTEM") { + nextchar += 6; + tokenizer = after_doctype_system_keyword_state; + } + else { + forcequirks(); + tokenizer = bogus_doctype_state; + } + break; + } + } + after_doctype_name_state.lookahead = 6; + + function after_doctype_public_keyword_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = before_doctype_public_identifier_state; + break; + case 0x0022: // QUOTATION MARK + beginDoctypePublicId(); + tokenizer = doctype_public_identifier_double_quoted_state; + break; + case 0x0027: // APOSTROPHE + beginDoctypePublicId(); + tokenizer = doctype_public_identifier_single_quoted_state; + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + forcequirks(); + tokenizer = bogus_doctype_state; + break; + } + } + + function before_doctype_public_identifier_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + break; + case 0x0022: // QUOTATION MARK + beginDoctypePublicId(); + tokenizer = doctype_public_identifier_double_quoted_state; + break; + case 0x0027: // APOSTROPHE + beginDoctypePublicId(); + tokenizer = doctype_public_identifier_single_quoted_state; + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + forcequirks(); + tokenizer = bogus_doctype_state; + break; + } + } + + function doctype_public_identifier_double_quoted_state(c) { + switch(c) { + case 0x0022: // QUOTATION MARK + tokenizer = after_doctype_public_identifier_state; + break; + case 0x0000: // NULL + appendChar(doctypepublicbuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(doctypepublicbuf, c); + break; + } + } + + function doctype_public_identifier_single_quoted_state(c) { + switch(c) { + case 0x0027: // APOSTROPHE + tokenizer = after_doctype_public_identifier_state; + break; + case 0x0000: // NULL + appendChar(doctypepublicbuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(doctypepublicbuf, c); + break; + } + } + + function after_doctype_public_identifier_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = between_doctype_public_and_system_identifiers_state; + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitDoctype(); + break; + case 0x0022: // QUOTATION MARK + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_double_quoted_state; + break; + case 0x0027: // APOSTROPHE + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_single_quoted_state; + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + forcequirks(); + tokenizer = bogus_doctype_state; + break; + } + } + + function between_doctype_public_and_system_identifiers_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE Ignore the character. + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitDoctype(); + break; + case 0x0022: // QUOTATION MARK + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_double_quoted_state; + break; + case 0x0027: // APOSTROPHE + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_single_quoted_state; + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + forcequirks(); + tokenizer = bogus_doctype_state; + break; + } + } + + function after_doctype_system_keyword_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + tokenizer = before_doctype_system_identifier_state; + break; + case 0x0022: // QUOTATION MARK + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_double_quoted_state; + break; + case 0x0027: // APOSTROPHE + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_single_quoted_state; + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + forcequirks(); + tokenizer = bogus_doctype_state; + break; + } + } + + function before_doctype_system_identifier_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE Ignore the character. + break; + case 0x0022: // QUOTATION MARK + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_double_quoted_state; + break; + case 0x0027: // APOSTROPHE + beginDoctypeSystemId(); + tokenizer = doctype_system_identifier_single_quoted_state; + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + forcequirks(); + tokenizer = bogus_doctype_state; + break; + } + } + + function doctype_system_identifier_double_quoted_state(c) { + switch(c) { + case 0x0022: // QUOTATION MARK + tokenizer = after_doctype_system_identifier_state; + break; + case 0x0000: // NULL + appendChar(doctypesystembuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(doctypesystembuf, c); + break; + } + } + + function doctype_system_identifier_single_quoted_state(c) { + switch(c) { + case 0x0027: // APOSTROPHE + tokenizer = after_doctype_system_identifier_state; + break; + case 0x0000: // NULL + appendChar(doctypesystembuf, 0xFFFD /* REPLACEMENT CHARACTER */); + break; + case 0x003E: // GREATER-THAN SIGN + forcequirks(); + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + appendChar(doctypesystembuf, c); + break; + } + } + + function after_doctype_system_identifier_state(c) { + switch(c) { + case 0x0009: // CHARACTER TABULATION (tab) + case 0x000A: // LINE FEED (LF) + case 0x000C: // FORM FEED (FF) + case 0x0020: // SPACE + /* Ignore the character. */ + break; + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + forcequirks(); + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + tokenizer = bogus_doctype_state; + /* This does *not* set the DOCTYPE token's force-quirks flag. */ + break; + } + } + + function bogus_doctype_state(c) { + switch(c) { + case 0x003E: // GREATER-THAN SIGN + tokenizer = data_state; + emitDoctype(); + break; + case EOF: + emitDoctype(); + nextchar--; // pushback + tokenizer = data_state; + break; + default: + /* Ignore the character. */ + break; + } + } + + function cdata_section_state(c, lookahead, eof) { + var len = lookahead.length; + var output; + if (eof) { + nextchar += len-1; // leave the EOF in the scanner + output = substring(lookahead,0, len-1); // don't include the EOF + } + else { + nextchar += len; + output = substring(lookahead,0,len-3); // don't emit the ]]> + } + + if (output.length > 0) { + if (output.indexOf("\u0000") !== -1) + textIncludesNUL = true; + + // XXX Have to deal with CR and CRLF here? + if (output.indexOf("\r") !== -1) { + output = output.replace(/\r\n/, "\n").replace(/\r/, "\n"); + } + + emitCharString(output); + } + + tokenizer = data_state; + } + cdata_section_state.lookahead = "]]>"; + + + /*** + * The tree builder insertion modes + */ + + // 11.2.5.4.1 The "initial" insertion mode + function initial_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + value = replace(value,LEADINGWS, ""); // Ignore spaces + if (value.length === 0) return; // Are we done? + break; // Handle anything non-space text below + case COMMENT: + doc.appendChild(doc.createComment(value)); + return; + case DOCTYPE: + var name = value; + var publicid = arg3; + var systemid = arg4; + // Use the constructor directly instead of + // implementation.createDocumentType because the create + // function throws errors on invalid characters, and + // we don't want the parser to throw them. + doc.appendChild(new impl.DocumentType(name,publicid, systemid)); + + // Note that there is no public API for setting quirks mode We can + // do this here because we have access to implementation details + if (force_quirks || + toLowerCase(name) !== "html" || + test(quirkyPublicIds, publicid) || + (systemid && toLowerCase(systemid) === quirkySystemId) || + (systemid === undefined && + test(conditionallyQuirkyPublicIds, publicid))) + doc._quirks = true; + else if (test(limitedQuirkyPublicIds, publicid) || + (systemid !== undefined && + test(conditionallyQuirkyPublicIds, publicid))) + doc._limitedQuirks = true; + parser = before_html_mode; + return; + } + + // tags or non-whitespace text + doc._quirks = true; + parser = before_html_mode; + parser(t,value,arg3,arg4); + } + + // 11.2.5.4.2 The "before html" insertion mode + function before_html_mode(t,value,arg3,arg4) { + var elt; + switch(t) { + case TEXT: + value = replace(value, LEADINGWS, ""); // Ignore spaces + if (value.length === 0) return; // Are we done? + break; // Handle anything non-space text below + case DOCTYPE: + /* ignore the token */ + return; + case COMMENT: + doc.appendChild(doc.createComment(value)); + return; + case TAG: + if (value === "html") { + elt = createHTMLElt(value, arg3); + stack.push(elt); + doc.appendChild(elt); + // XXX: handle application cache here + parser = before_head_mode; + return; + } + break; + case ENDTAG: + switch(value) { + case "html": + case "head": + case "body": + case "br": + break; // fall through on these + default: + return; // ignore most end tags + } + } + + // Anything that didn't get handled above is handled like this: + elt = createHTMLElt("html", null); + stack.push(elt); + doc.appendChild(elt); + // XXX: handle application cache here + parser = before_head_mode; + parser(t,value,arg3,arg4); + } + + // 11.2.5.4.3 The "before head" insertion mode + function before_head_mode(t,value,arg3,arg4) { + switch(t) { + case TEXT: + value = replace(value, LEADINGWS, ""); // Ignore spaces + if (value.length === 0) return; // Are we done? + break; // Handle anything non-space text below + case DOCTYPE: + /* ignore the token */ + return; + case COMMENT: + insertComment(value); + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t,value,arg3,arg4); + return; + case "head": + var elt = insertHTMLElement(value, arg3); + head_element_pointer = elt; + parser = in_head_mode; + return; + } + break; + case ENDTAG: + switch(value) { + case "html": + case "head": + case "body": + case "br": + break; + default: + return; // ignore most end tags + } + } + + // If not handled explicitly above + before_head_mode(TAG, "head", null); // create a head tag + parser(t, value, arg3, arg4); // then try again with this token + } + + function in_head_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + var ws = match(value, LEADINGWS); + if (ws) { + insertText(ws[0]); + value = substring(value,ws[0].length); + } + if (value.length === 0) return; + break; // Handle non-whitespace below + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "meta": + // XXX: + // May need to change the encoding based on this tag + /* falls through */ + case "base": + case "basefont": + case "bgsound": + case "command": + case "link": + insertHTMLElement(value, arg3); + stack.pop(); + return; + case "title": + parseRCDATA(value, arg3); + return; + case "noscript": + if (!scripting_enabled) { + insertHTMLElement(value, arg3); + parser = in_head_noscript_mode; + return; + } + // Otherwise, if scripting is enabled... + /* falls through */ + case "noframes": + case "style": + parseRawText(value,arg3); + return; + case "script": + var elt = createHTMLElt(value, arg3); + elt._parser_inserted = true; + elt._force_async = false; + if (fragment) elt._already_started = true; + flushText(); + stack.top.appendChild(elt); + stack.push(elt); + tokenizer = script_data_state; + originalInsertionMode = parser; + parser = text_mode; + return; + case "head": + return; // ignore it + } + break; + case ENDTAG: + switch(value) { + case "head": + stack.pop(); + parser = after_head_mode; + return; + case "body": + case "html": + case "br": + break; // handle these at the bottom of the function + default: + // ignore any other end tag + return; + } + break; + } + + // If not handled above + in_head_mode(ENDTAG, "head", null); // synthetic + parser(t, value, arg3, arg4); // Then redo this one + } + + // 13.2.5.4.5 The "in head noscript" insertion mode + function in_head_noscript_mode(t, value, arg3, arg4) { + switch(t) { + case DOCTYPE: + return; + case COMMENT: + in_head_mode(t, value); + return; + case TEXT: + var ws = match(value, LEADINGWS); + if (ws) { + in_head_mode(t, ws[0]); + value = substring(value,ws[0].length); + } + if (value.length === 0) return; // no more text + break; // Handle non-whitespace below + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "basefont": + case "bgsound": + case "link": + case "meta": + case "noframes": + case "style": + in_head_mode(t, value, arg3); + return; + case "head": + case "noscript": + return; + } + break; + case ENDTAG: + switch(value) { + case "noscript": + stack.pop(); + parser = in_head_mode; + return; + case "br": + break; // goes to the outer default + default: + return; // ignore other end tags + } + break; + } + + // If not handled above + in_head_noscript_mode(ENDTAG, "noscript", null); + parser(t, value, arg3, arg4); + } + + function after_head_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + var ws = match(value, LEADINGWS); + if (ws) { + insertText(ws[0]); + value = substring(value,ws[0].length); + } + if (value.length === 0) return; + break; // Handle non-whitespace below + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "body": + insertHTMLElement(value, arg3); + frameset_ok = false; + parser = in_body_mode; + return; + case "frameset": + insertHTMLElement(value, arg3); + parser = in_frameset_mode; + return; + case "base": + case "basefont": + case "bgsound": + case "link": + case "meta": + case "noframes": + case "script": + case "style": + case "title": + stack.push(head_element_pointer); + in_head_mode(TAG, value, arg3); + stack.removeElement(head_element_pointer); + return; + case "head": + return; + } + break; + case ENDTAG: + switch(value) { + case "body": + case "html": + case "br": + break; + default: + return; // ignore any other end tag + } + break; + } + + after_head_mode(TAG, "body", null); + frameset_ok = true; + parser(t, value, arg3, arg4); + } + + // 13.2.5.4.7 The "in body" insertion mode + function in_body_mode(t,value,arg3,arg4) { + var body, i, node; + switch(t) { + case TEXT: + if (textIncludesNUL) { + value = replace(value, NULCHARS, ""); + if (value.length === 0) return; + } + // If any non-space characters + if (frameset_ok && test(NONWS, value)) + frameset_ok = false; + afereconstruct(); + insertText(value); + return; + case DOCTYPE: + return; + case COMMENT: + insertComment(value); + return; + case EOF: + stopParsing(); + return; + case TAG: + switch(value) { + case "html": + transferAttributes(arg3, stack.elements[0]); + return; + case "base": + case "basefont": + case "bgsound": + case "command": + case "link": + case "meta": + case "noframes": + case "script": + case "style": + case "title": + in_head_mode(TAG, value, arg3); + return; + case "body": + body = stack.elements[1]; + if (!body || !(body instanceof impl.HTMLBodyElement)) + return; + frameset_ok = false; + transferAttributes(arg3, body); + return; + case "frameset": + if (!frameset_ok) return; + body = stack.elements[1]; + if (!body || !(body instanceof impl.HTMLBodyElement)) + return; + if (body.parentNode) body.parentNode.removeChild(body); + while(!(stack.top instanceof impl.HTMLHtmlElement)) + stack.pop(); + insertHTMLElement(value, arg3); + parser = in_frameset_mode; + return; + + case "address": + case "article": + case "aside": + case "blockquote": + case "center": + case "details": + case "dir": + case "div": + case "dl": + case "fieldset": + case "figcaption": + case "figure": + case "footer": + case "header": + case "hgroup": + case "menu": + case "nav": + case "ol": + case "p": + case "section": + case "summary": + case "ul": + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + insertHTMLElement(value, arg3); + return; + + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + if (stack.top instanceof impl.HTMLHeadingElement) + stack.pop(); + insertHTMLElement(value, arg3); + return; + + case "pre": + case "listing": + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + insertHTMLElement(value, arg3); + ignore_linefeed = true; + frameset_ok = false; + return; + + case "form": + if (form_element_pointer) return; + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + form_element_pointer = insertHTMLElement(value, arg3); + return; + + case "li": + frameset_ok = false; + for(i = stack.elements.length-1; i >= 0; i--) { + node = stack.elements[i]; + if (node instanceof impl.HTMLLIElement) { + in_body_mode(ENDTAG, "li"); + break; + } + if (isA(node, specialSet) && !isA(node, addressdivpSet)) + break; + } + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + insertHTMLElement(value, arg3); + return; + + case "dd": + case "dt": + frameset_ok = false; + for(i = stack.elements.length-1; i >= 0; i--) { + node = stack.elements[i]; + if (isA(node, dddtSet)) { + in_body_mode(ENDTAG, node.localName); + break; + } + if (isA(node, specialSet) && !isA(node, addressdivpSet)) + break; + } + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + insertHTMLElement(value, arg3); + return; + + case "plaintext": + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + insertHTMLElement(value, arg3); + tokenizer = plaintext_state; + return; + + case "button": + if (stack.inScope("button")) { + in_body_mode(ENDTAG, "button"); + parser(t, value, arg3, arg4); + } + else { + afereconstruct(); + insertHTMLElement(value, arg3); + frameset_ok = false; + } + return; + + case "a": + var activeElement = afe.findElementByTag("a"); + if (activeElement) { + in_body_mode(ENDTAG, value); + afe.remove(activeElement); + stack.removeElement(activeElement); + } + /* falls through */ + + case "b": + case "big": + case "code": + case "em": + case "font": + case "i": + case "s": + case "small": + case "strike": + case "strong": + case "tt": + case "u": + afereconstruct(); + afe.push(insertHTMLElement(value,arg3), arg3); + return; + + case "nobr": + afereconstruct(); + + if (stack.inScope(value)) { + in_body_mode(ENDTAG, value); + afereconstruct(); + } + afe.push(insertHTMLElement(value,arg3), arg3); + return; + + case "applet": + case "marquee": + case "object": + afereconstruct(); + insertHTMLElement(value,arg3); + afe.insertMarker(); + frameset_ok = false; + return; + + case "table": + if (!doc._quirks && stack.inButtonScope("p")) { + in_body_mode(ENDTAG, "p"); + } + insertHTMLElement(value,arg3); + frameset_ok = false; + parser = in_table_mode; + return; + + case "area": + case "br": + case "embed": + case "img": + case "keygen": + case "wbr": + afereconstruct(); + insertHTMLElement(value,arg3); + stack.pop(); + frameset_ok = false; + return; + + case "input": + afereconstruct(); + var elt = insertHTMLElement(value,arg3); + stack.pop(); + var type = elt.getAttribute("type"); + if (!type || toLowerCase(type) !== "hidden") + frameset_ok = false; + return; + + case "param": + case "source": + case "track": + insertHTMLElement(value,arg3); + stack.pop(); + return; + + case "hr": + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + insertHTMLElement(value,arg3); + stack.pop(); + frameset_ok = false; + return; + + case "image": + in_body_mode(TAG, "img", arg3, arg4); + return; + + case "isindex": + if (form_element_pointer) return; + (function handleIsIndexTag(attrs) { + var prompt = null; + var formattrs = []; + var newattrs = [["name", "isindex"]]; + for(var i = 0; i < attrs.length; i++) { + var a = attrs[i]; + if (a[0] === "action") { + push(formattrs, a); + } + else if (a[0] === "prompt") { + prompt = a[1]; + } + else if (a[0] !== "name") { + push(newattrs, a); + } + } + + // This default prompt presumably needs localization. + // The space after the colon in this prompt is required + // by the html5lib test cases + if (!prompt) + prompt = "This is a searchable index. " + + "Enter search keywords: "; + + parser(TAG, "form", formattrs); + parser(TAG, "hr", null); + parser(TAG, "label", null); + parser(TEXT, prompt); + parser(TAG, "input", newattrs); + parser(ENDTAG, "label"); + parser(TAG, "hr", null); + parser(ENDTAG, "form"); + }(arg3)); + return; + + case "textarea": + insertHTMLElement(value,arg3); + ignore_linefeed = true; + frameset_ok = false; + tokenizer = rcdata_state; + originalInsertionMode = parser; + parser = text_mode; + return; + + case "xmp": + if (stack.inButtonScope("p")) in_body_mode(ENDTAG, "p"); + afereconstruct(); + frameset_ok = false; + parseRawText(value, arg3); + return; + + case "iframe": + frameset_ok = false; + parseRawText(value, arg3); + return; + + case "noembed": + parseRawText(value,arg3); + return; + + case "noscript": + if (scripting_enabled) { + parseRawText(value,arg3); + return; + } + break; // XXX Otherwise treat it as any other open tag? + + case "select": + afereconstruct(); + insertHTMLElement(value,arg3); + frameset_ok = false; + if (parser === in_table_mode || + parser === in_caption_mode || + parser === in_table_body_mode || + parser === in_row_mode || + parser === in_cell_mode) + parser = in_select_in_table_mode; + else + parser = in_select_mode; + return; + + case "optgroup": + case "option": + if (stack.top instanceof impl.HTMLOptionElement) { + in_body_mode(ENDTAG, "option"); + } + afereconstruct(); + insertHTMLElement(value,arg3); + return; + + case "rp": + case "rt": + if (stack.inScope("ruby")) { + stack.generateImpliedEndTags(); + } + insertHTMLElement(value,arg3); + return; + + case "math": + afereconstruct(); + adjustMathMLAttributes(arg3); + adjustForeignAttributes(arg3); + insertForeignElement(value, arg3, MATHML_NAMESPACE); + if (arg4) // self-closing flag + stack.pop(); + return; + + case "svg": + afereconstruct(); + adjustSVGAttributes(arg3); + adjustForeignAttributes(arg3); + insertForeignElement(value, arg3, SVG_NAMESPACE); + if (arg4) // self-closing flag + stack.pop(); + return; + + case "caption": + case "col": + case "colgroup": + case "frame": + case "head": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + // Ignore table tags if we're not in_table mode + return; + } + + // Handle any other start tag here + // (and also noscript tags when scripting is disabled) + afereconstruct(); + insertHTMLElement(value,arg3); + return; + + case ENDTAG: + switch(value) { + case "body": + if (!stack.inScope("body")) return; + parser = after_body_mode; + return; + case "html": + if (!stack.inScope("body")) return; + parser = after_body_mode; + parser(t, value, arg3); + return; + + case "address": + case "article": + case "aside": + case "blockquote": + case "button": + case "center": + case "details": + case "dir": + case "div": + case "dl": + case "fieldset": + case "figcaption": + case "figure": + case "footer": + case "header": + case "hgroup": + case "listing": + case "menu": + case "nav": + case "ol": + case "pre": + case "section": + case "summary": + case "ul": + // Ignore if there is not a matching open tag + if (!stack.inScope(value)) return; + stack.generateImpliedEndTags(); + stack.popTag(value); + return; + + case "form": + var openform = form_element_pointer; + form_element_pointer = null; + if (!openform || !stack.elementInScope(openform)) return; + stack.generateImpliedEndTags(); + stack.removeElement(openform); + return; + + case "p": + if (!stack.inButtonScope(value)) { + in_body_mode(TAG, value, null); + parser(t, value, arg3, arg4); + } + else { + stack.generateImpliedEndTags(value); + stack.popTag(value); + } + return; + + case "li": + if (!stack.inListItemScope(value)) return; + stack.generateImpliedEndTags(value); + stack.popTag(value); + return; + + case "dd": + case "dt": + if (!stack.inScope(value)) return; + stack.generateImpliedEndTags(value); + stack.popTag(value); + return; + + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + if (!stack.elementTypeInScope(impl.HTMLHeadingElement)) return; + stack.generateImpliedEndTags(); + stack.popElementType(impl.HTMLHeadingElement); + return; + + case "a": + case "b": + case "big": + case "code": + case "em": + case "font": + case "i": + case "nobr": + case "s": + case "small": + case "strike": + case "strong": + case "tt": + case "u": + var result = adoptionAgency(value); + if (result) return; // If we did something we're done + break; // Go to the "any other end tag" case + + case "applet": + case "marquee": + case "object": + if (!stack.inScope(value)) return; + stack.generateImpliedEndTags(); + stack.popTag(value); + afe.clearToMarker(); + return; + + case "br": + in_body_mode(TAG, value, null); // Turn
    into
    + return; + } + + // Any other end tag goes here + for(i = stack.elements.length-1; i >= 0; i--) { + node = stack.elements[i]; + if (node.localName === value) { + stack.generateImpliedEndTags(value); + stack.popElement(node); + break; + } + else if (isA(node, specialSet)) { + return; + } + } + + return; + } + } + + function text_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + insertText(value); + return; + case EOF: + if (stack.top instanceof impl.HTMLScriptElement) + stack.top._already_started = true; + stack.pop(); + parser = originalInsertionMode; + parser(t); + return; + case ENDTAG: + if (value === "script") { + handleScriptEnd(); + } + else { + stack.pop(); + parser = originalInsertionMode; + } + return; + default: + // We should never get any other token types + return; + } + } + + function in_table_mode(t, value, arg3, arg4) { + function getTypeAttr(attrs) { + for(var i = 0, n = attrs.length; i < n; i++) { + if (attrs[i][0] === "type") + return toLowerCase(attrs[i][1]); + } + return null; + } + + switch(t) { + case TEXT: + // XXX the text_integration_mode stuff is + // just a hack I made up + if (text_integration_mode) { + in_body_mode(t, value, arg3, arg4) + } + else { + pending_table_text = []; + originalInsertionMode = parser; + parser = in_table_text_mode; + parser(t, value, arg3, arg4); + } + return; + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case TAG: + switch(value) { + case "caption": + stack.clearToContext(impl.HTMLTableElement); + afe.insertMarker(); + insertHTMLElement(value,arg3); + parser = in_caption_mode; + return; + case "colgroup": + stack.clearToContext(impl.HTMLTableElement); + insertHTMLElement(value,arg3); + parser = in_column_group_mode; + return; + case "col": + in_table_mode(TAG, "colgroup", null); + parser(t, value, arg3, arg4); + return; + case "tbody": + case "tfoot": + case "thead": + stack.clearToContext(impl.HTMLTableElement); + insertHTMLElement(value,arg3); + parser = in_table_body_mode; + return; + case "td": + case "th": + case "tr": + in_table_mode(TAG, "tbody", null); + parser(t, value, arg3, arg4); + return; + + case "table": + var repro = stack.inTableScope(value); + in_table_mode(ENDTAG, value); + if (repro) parser(t, value, arg3, arg4); + return; + + case "style": + case "script": + in_head_mode(t, value, arg3, arg4); + return; + + case "input": + var type = getTypeAttr(arg3); + if (type !== "hidden") break; // to the anything else case + insertHTMLElement(value,arg3); + stack.pop(); + return; + + case "form": + if (form_element_pointer) return; + form_element_pointer = insertHTMLElement(value, arg3); + stack.pop(); + return; + } + break; + case ENDTAG: + switch(value) { + case "table": + if (!stack.inTableScope(value)) return; + stack.popTag(value); + resetInsertionMode(); + return; + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + return; + } + + break; + case EOF: + stopParsing(); + return; + } + + // This is the anything else case + foster_parent_mode = true; + in_body_mode(t, value, arg3, arg4); + foster_parent_mode = false; + } + + function in_table_text_mode(t, value, arg3, arg4) { + if (t === TEXT) { + if (textIncludesNUL) { + value = replace(value, NULCHARS, ""); + if (value.length === 0) return; + } + push(pending_table_text,value); + } + else { + var s = join(pending_table_text,""); + pending_table_text.length = 0; + if (test(NONWS, s)) { // If any non-whitespace characters + // This must be the same code as the "anything else" + // case of the in_table mode above. + foster_parent_mode = true; + in_body_mode(TEXT, s); + foster_parent_mode = false; + } + else { + insertText(s); + } + parser = originalInsertionMode; + parser(t, value, arg3, arg4); + } + } + + + function in_caption_mode(t, value, arg3, arg4) { + function end_caption() { + if (!stack.inTableScope("caption")) return false; + stack.generateImpliedEndTags(); + stack.popTag("caption"); + afe.clearToMarker(); + parser = in_table_mode; + return true; + } + + switch(t) { + case TAG: + switch(value) { + case "caption": + case "col": + case "colgroup": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + if (end_caption()) parser(t, value, arg3, arg4); + return; + } + break; + case ENDTAG: + switch(value) { + case "caption": + end_caption(); + return; + case "table": + if (end_caption()) parser(t, value, arg3, arg4); + return; + case "body": + case "col": + case "colgroup": + case "html": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + return; + } + break; + } + + // The Anything Else case + in_body_mode(t, value, arg3, arg4); + } + + function in_column_group_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + var ws = match(value, LEADINGWS); + if (ws) { + insertText(ws[0]); + value = substring(value,ws[0].length); + } + if (value.length === 0) return; + break; // Handle non-whitespace below + + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "col": + insertHTMLElement(value, arg3); + stack.pop(); + return; + } + break; + case ENDTAG: + switch(value) { + case "colgroup": + if (stack.top instanceof impl.HTMLHtmlElement) return; + stack.pop(); + parser = in_table_mode; + return; + case "col": + return; + } + break; + case EOF: + if (stack.top instanceof impl.HTMLHtmlElement) { + stopParsing(); + return; + } + break; + } + + // Anything else + if (!(stack.top instanceof impl.HTMLHtmlElement)) { + in_column_group_mode(ENDTAG, "colgroup"); + parser(t, value, arg3, arg4); + } + } + + function in_table_body_mode(t, value, arg3, arg4) { + function endsect() { + if (!stack.inTableScope("tbody") && + !stack.inTableScope("thead") && + !stack.inTableScope("tfoot")) + return; + stack.clearToContext(impl.HTMLTableSectionElement); + in_table_body_mode(ENDTAG, stack.top.localName, null); + parser(t, value, arg3, arg4); + } + + switch(t) { + case TAG: + switch(value) { + case "tr": + stack.clearToContext(impl.HTMLTableSectionElement); + insertHTMLElement(value, arg3); + parser = in_row_mode; + return; + case "th": + case "td": + in_table_body_mode(TAG, "tr", null); + parser(t, value, arg3, arg4); + return; + case "caption": + case "col": + case "colgroup": + case "tbody": + case "tfoot": + case "thead": + endsect(); + return; + } + break; + case ENDTAG: + switch(value) { + case "table": + endsect(); + return; + case "tbody": + case "tfoot": + case "thead": + if (stack.inTableScope(value)) { + stack.clearToContext(impl.HTMLTableSectionElement); + stack.pop(); + parser = in_table_mode; + } + return; + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + case "td": + case "th": + case "tr": + return; + } + break; + } + + // Anything else: + in_table_mode(t, value, arg3, arg4); + } + + function in_row_mode(t, value, arg3, arg4) { + function endrow() { + if (!stack.inTableScope("tr")) return false; + stack.clearToContext(impl.HTMLTableRowElement); + stack.pop(); + parser = in_table_body_mode; + return true; + } + + switch(t) { + case TAG: + switch(value) { + case "th": + case "td": + stack.clearToContext(impl.HTMLTableRowElement); + insertHTMLElement(value, arg3); + parser = in_cell_mode; + afe.insertMarker(); + return; + case "caption": + case "col": + case "colgroup": + case "tbody": + case "tfoot": + case "thead": + case "tr": + if (endrow()) parser(t, value, arg3, arg4); + return; + } + break; + case ENDTAG: + switch(value) { + case "tr": + endrow(); + return; + case "table": + if (endrow()) parser(t, value, arg3, arg4); + return; + case "tbody": + case "tfoot": + case "thead": + if (stack.inTableScope(value)) { + in_row_mode(ENDTAG, "tr"); + parser(t, value, arg3, arg4); + } + return; + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + case "td": + case "th": + return; + } + break; + } + + // anything else + in_table_mode(t, value, arg3, arg4); + } + + function in_cell_mode(t, value, arg3, arg4) { + switch(t) { + case TAG: + switch(value) { + case "caption": + case "col": + case "colgroup": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + if (stack.inTableScope("td")) { + in_cell_mode(ENDTAG, "td"); + parser(t, value, arg3, arg4); + } + else if (stack.inTableScope("th")) { + in_cell_mode(ENDTAG, "th"); + parser(t, value, arg3, arg4); + } + return; + } + break; + case ENDTAG: + switch(value) { + case "td": + case "th": + if (!stack.inTableScope(value)) return; + stack.generateImpliedEndTags(); + stack.popTag(value); + afe.clearToMarker(); + parser = in_row_mode; + return; + + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + return; + + case "table": + case "tbody": + case "tfoot": + case "thead": + case "tr": + if (!stack.inTableScope(value)) return; + in_cell_mode(ENDTAG, stack.inTableScope("td") ? "td" : "th"); + parser(t, value, arg3, arg4); + return; + } + break; + } + + // anything else + in_body_mode(t, value, arg3, arg4); + } + + function in_select_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + if (textIncludesNUL) { + value = replace(value, NULCHARS, ""); + if (value.length === 0) return; + } + insertText(value); + return; + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case EOF: + stopParsing(); + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "option": + if (stack.top instanceof impl.HTMLOptionElement) + in_select_mode(ENDTAG, value); + insertHTMLElement(value, arg3); + return; + case "optgroup": + if (stack.top instanceof impl.HTMLOptionElement) + in_select_mode(ENDTAG, "option"); + if (stack.top instanceof impl.HTMLOptGroupElement) + in_select_mode(ENDTAG, value); + insertHTMLElement(value, arg3); + return; + case "select": + in_select_mode(ENDTAG, value); // treat it as a close tag + return; + + case "input": + case "keygen": + case "textarea": + if (!stack.inSelectScope("select")) return; + in_select_mode(ENDTAG, "select"); + parser(t, value, arg3, arg4); + return; + + case "script": + in_head_mode(t, value, arg3, arg4); + return; + } + break; + case ENDTAG: + switch(value) { + case "optgroup": + if (stack.top instanceof impl.HTMLOptionElement && + stack.elements[stack.elements.length-2] instanceof + impl.HTMLOptGroupElement) { + in_select_mode(ENDTAG, "option"); + } + if (stack.top instanceof impl.HTMLOptGroupElement) + stack.pop(); + + return; + + case "option": + if (stack.top instanceof impl.HTMLOptionElement) + stack.pop(); + return; + + case "select": + if (!stack.inSelectScope(value)) return; + stack.popTag(value); + resetInsertionMode(); + return; + } + + break; + } + + // anything else: just ignore the token + } + + function in_select_in_table_mode(t, value, arg3, arg4) { + switch(value) { + case "caption": + case "table": + case "tbody": + case "tfoot": + case "thead": + case "tr": + case "td": + case "th": + switch(t) { + case TAG: + in_select_in_table_mode(ENDTAG, "select"); + parser(t, value, arg3, arg4); + return; + case ENDTAG: + if (stack.inTableScope(value)) { + in_select_in_table_mode(ENDTAG, "select"); + parser(t, value, arg3, arg4); + } + return; + } + } + + // anything else + in_select_mode(t, value, arg3, arg4); + } + + function after_body_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + // If any non-space chars, handle below + if (test(NONWS, value)) break; + in_body_mode(t, value); + return; + case COMMENT: + // Append it to the element + stack.elements[0].appendChild(doc.createComment(value)); + return; + case DOCTYPE: + return; + case EOF: + stopParsing(); + return; + case TAG: + if (value === "html") { + in_body_mode(t, value, arg3, arg4); + return; + } + break; // for any other tags + case ENDTAG: + if (value === "html") { + if (fragment) return; + parser = after_after_body_mode; + return; + } + break; // for any other tags + } + + // anything else + parser = in_body_mode; + parser(t, value, arg3, arg4); + } + + function in_frameset_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + // Ignore any non-space characters + value = replace(value, ALLNONWS, ""); + if (value.length > 0) insertText(value); + return; + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case EOF: + stopParsing(); + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "frameset": + insertHTMLElement(value, arg3); + return; + case "frame": + insertHTMLElement(value, arg3); + stack.pop(); + return; + case "noframes": + in_head_mode(t, value, arg3, arg4); + return; + } + break; + case ENDTAG: + if (value === "frameset") { + if (fragment && stack.top instanceof impl.HTMLHtmlElement) + return; + stack.pop(); + if (!fragment && + !(stack.top instanceof impl.HTMLFrameSetElement)) + parser = after_frameset_mode; + return; + } + break; + } + + // ignore anything else + } + + function after_frameset_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + // Ignore any non-space characters + value = replace(value, ALLNONWS, ""); + if (value.length > 0) insertText(value); + return; + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + return; + case EOF: + stopParsing(); + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "noframes": + in_head_mode(t, value, arg3, arg4); + return; + } + break; + case ENDTAG: + if (value === "html") { + parser = after_after_frameset_mode; + return; + } + break; + } + + // ignore anything else + } + + function after_after_body_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + // If any non-space chars, handle below + if (test(NONWS, value)) break; + in_body_mode(t, value, arg3, arg4); + return; + case COMMENT: + doc.appendChild(doc.createComment(value)); + return; + case DOCTYPE: + in_body_mode(t, value, arg3, arg4); + return; + case EOF: + stopParsing(); + return; + case TAG: + if (value === "html") { + in_body_mode(t, value, arg3, arg4); + return; + } + break; + } + + // anything else + parser = in_body_mode; + parser(t, value, arg3, arg4); + } + + function after_after_frameset_mode(t, value, arg3, arg4) { + switch(t) { + case TEXT: + // Ignore any non-space characters + value = replace(value, ALLNONWS, ""); + if (value.length > 0) + in_body_mode(t, value, arg3, arg4); + return; + case COMMENT: + doc.appendChild(doc.createComment(value)); + return; + case DOCTYPE: + in_body_mode(t, value, arg3, arg4); + return; + case EOF: + stopParsing(); + return; + case TAG: + switch(value) { + case "html": + in_body_mode(t, value, arg3, arg4); + return; + case "noframes": + in_head_mode(t, value, arg3, arg4); + return; + } + break; + } + + // ignore anything else + } + + + // 13.2.5.5 The rules for parsing tokens in foreign content + // + // This is like one of the insertion modes above, but is + // invoked somewhat differently when the current token is not HTML. + // See the insertToken() function. + function insertForeignToken(t, value, arg3, arg4) { + // A tag is an HTML font tag if it has a color, font, or size + // attribute. Otherwise we assume it is foreign content + function isHTMLFont(attrs) { + for(var i = 0, n = attrs.length; i < n; i++) { + switch(attrs[i][0]) { + case "color": + case "font": + case "size": + return true; + } + } + return false; + } + + var current; + + switch(t) { + case TEXT: + // If any non-space, non-nul characters + if (frameset_ok && test(NONWSNONNUL, value)) + frameset_ok = false; + if (textIncludesNUL) { + value = replace(value, NULCHARS, "\uFFFD"); + } + insertText(value); + return; + case COMMENT: + insertComment(value); + return; + case DOCTYPE: + // ignore it + return; + case TAG: + switch(value) { + case "font": + if (!isHTMLFont(arg3)) break; + /* falls through */ + case "b": + case "big": + case "blockquote": + case "body": + case "br": + case "center": + case "code": + case "dd": + case "div": + case "dl": + case "dt": + case "em": + case "embed": + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + case "head": + case "hr": + case "i": + case "img": + case "li": + case "listing": + case "menu": + case "meta": + case "nobr": + case "ol": + case "p": + case "pre": + case "ruby": + case "s": + case "small": + case "span": + case "strong": + case "strike": + case "sub": + case "sup": + case "table": + case "tt": + case "u": + case "ul": + case "var": + do { + stack.pop(); + current = stack.top; + } while(current.namespaceURI !== HTML_NAMESPACE && + !isMathmlTextIntegrationPoint(current) && + !isHTMLIntegrationPoint(current)); + + insertToken(t, value, arg3, arg4); // reprocess + return; + } + + // Any other start tag case goes here + current = stack.top; + if (current.namespaceURI === MATHML_NAMESPACE) { + adjustMathMLAttributes(arg3); + } + else if (current.namespaceURI === SVG_NAMESPACE) { + value = adjustSVGTagName(value); + adjustSVGAttributes(arg3); + } + adjustForeignAttributes(arg3) + + insertForeignElement(value, arg3, current.namespaceURI); + if (arg4) // the self-closing flag + stack.pop(); + return; + + case ENDTAG: + current = stack.top; + if (value === "script" && + current.namespaceURI === SVG_NAMESPACE && + current.localName === "script") { + + stack.pop(); + + // XXX + // Deal with SVG scripts here + } + else { + // The any other end tag case + var i = stack.elements.length-1; + var node = stack.elements[i]; + for(;;) { + if (toLowerCase(node.localName) === value) { + stack.popElement(node); + break; + } + node = stack.elements[--i]; + // If non-html, keep looping + if (node.namespaceURI !== HTML_NAMESPACE) + continue; + // Otherwise process the end tag as html + parser(t, value, arg3, arg4); + break; + } + } + return; + } + } + + + /*** + * parsing code for character references + */ + + // Parse a character reference from s and return a codepoint or an + // array of codepoints or null if there is no valid char ref in s. + function parseCharRef(s, isattr) { + var len = s.length; + var rv; + if (len === 0) return null; // No character reference matched + + if (s[0] === "#") { // Numeric character reference + var codepoint; + + if (s[1] === "x" || s[1] === "X") { + // Hex + codepoint = parseInt(substring(s,2), 16); + } + else { + // Decimal + codepoint = parseInt(substring(s,1), 10); + } + + if (s[len-1] === ";") // If the string ends with a semicolon + nextchar += len; // Consume all the chars + else + nextchar += len-1; // Otherwise, all but the last character + + if (codepoint in numericCharRefReplacements) { + codepoint = numericCharRefReplacements[codepoint]; + } + else if (codepoint > 0x10FFFF || + (codepoint >= 0xD800 && codepoint < 0xE000)) { + codepoint = 0xFFFD; + } + + if (codepoint <= 0xFFFF) return codepoint; + + codepoint = codepoint - 0x10000; + return [0xD800 + (codepoint >> 10), + 0xDC00 + (codepoint & 0x03FF)]; + } + else { // Named character reference + // We have to be able to parse some named char refs even when + // the semicolon is omitted, but have to match the longest one + // possible. So if the lookahead doesn't end with semicolon + // then we have to loop backward looking for longest to shortest + // matches. Fortunately, the names that don't require semis + // are all between 2 and 6 characters long. + + if (s[len-1] === ";") { + rv = namedCharRefs[s]; + if (rv !== undefined) { + nextchar += len; // consume all the characters + return rv; + } + } + + // If it didn't end with a semicolon, see if we can match + // everything but the terminating character + len--; // Ignore whatever the terminating character is + rv = namedCharRefsNoSemi[substring(s,0, len)]; + if (rv !== undefined) { + nextchar += len; + return rv; + } + + // If it still didn't match, and we're not parsing a + // character reference in an attribute value, then try + // matching shorter substrings. + if (!isattr) { + len--; + if (len > 6) len = 6; // Maximum possible match length + while(len >= 2) { + rv = namedCharRefsNoSemi[substring(s,0, len)]; + if (rv !== undefined) { + nextchar += len; + return rv; + } + len--; + } + } + + // Couldn't find any match + return null; + } + } + + + /*** + * Finally, this is the end of the HTMLParser() factory function. + * It returns the htmlparser object with the append() and end() methods. + */ + + // Sneak another method into the htmlparser object to allow us to run + // tokenizer tests. This can be commented out in production code. + // This is a hook for testing the tokenizer. It has to be here + // because the tokenizer details are all hidden away within the closure. + // It should return an array of tokens generated while parsing the + // input string. + htmlparser.testTokenizer = function(input, initialState, + lastStartTag, charbychar) + { + var tokens = []; + + switch(initialState) { + case "PCDATA state": + tokenizer = data_state; + break; + case "RCDATA state": + tokenizer = rcdata_state; + break; + case "RAWTEXT state": + tokenizer = rawtext_state; + break; + case "PLAINTEXT state": + tokenizer = plaintext_state; + break; + } + + if (lastStartTag) { + lasttagname = lastStartTag; + } + + insertToken = function(t, value, arg3, arg4) { + flushText(); + switch(t) { + case TEXT: + if (tokens.length > 0 && + tokens[tokens.length-1][0] === "Character") { + tokens[tokens.length-1][1] += value; + } + else push(tokens, ["Character", value]); + break; + case COMMENT: + push(tokens,["Comment", value]); + break; + case DOCTYPE: + push(tokens,["DOCTYPE", value, + arg3 === undefined ? null : arg3, + arg4 === undefined ? null : arg4, + !force_quirks]); + break; + case TAG: + var attrs = {}; + for(var i = 0; i < arg3.length; i++) { + // XXX: does attribute order matter? + var a = arg3[i]; + if (a.length === 1) { + attrs[a[0]] = ""; + } + else { + attrs[a[0]] = a[1]; + } + } + var token = ["StartTag", value, attrs]; + if (arg4) push(token, true); + push(tokens,token); + break; + case ENDTAG: + push(tokens,["EndTag", value]); + break; + case EOF: + break; + } + } + + if (!charbychar) { + this.parse(input, true); + } + else { + for(var i = 0; i < input.length; i++) { + this.parse(input[i]); + } + this.parse("", true); + } + return tokens; + }; + + // Return the parser object from the HTMLParser() factory function + return htmlparser; + } + + // Return the HTMLParser factory function from the containing + // closure that holds all the details. + return HTMLParser; +}()); + + +/************************************************************************ + * src/impl/CSSStyleDeclaration.js + ************************************************************************/ + +//@line 1 "src/impl/CSSStyleDeclaration.js" +defineLazyProperty(impl, "CSSStyleDeclaration", function() { + function CSSStyleDeclaration(elt) { + this._element = elt; + } + + // Utility function for parsing style declarations + // Pass in a string like "margin-left: 5px; border-style: solid" + // and this function returns an object like + // {"margin-left":"5px", "border-style":"solid"} + function parseStyles(s) { + var parser = new parserlib.css.Parser(); + var result = {}; + parser.addListener("property", function(e) { + if (e.invalid) return; // Skip errors + result[e.property.text] = e.value.text; + if (e.important) result.important[name] = e.important; + }); + parser.parseStyleAttribute(s); + return result; + } + + CSSStyleDeclaration.prototype = O.create(Object.prototype, { + _idlName: constant("CSSStyleDeclaration"), + + // Return the parsed form of the element's style attribute. + // If the element's style attribute has never been parsed + // or if it has changed since the last parse, then reparse it + // Note that the styles don't get parsed until they're actually needed + _parsed: attribute(function() { + if (!this._parsedStyles || this.cssText !== this._lastParsedText) { + var text = this.cssText; + this._parsedStyles = parseStyles(text); + this._lastParsedText = text; + delete this._names; + } + return this._parsedStyles; + }), + + // Call this method any time the parsed representation of the + // style changes. It converts the style properties to a string and + // sets cssText and the element's style attribute + _serialize: constant(function() { + var styles = this._parsed; + var s = ""; + + for(var name in styles) { + if (s) s += "; "; + s += name + ":" + styles[name] + } + + this.cssText = s; // also sets the style attribute + this._lastParsedText = s; // so we don't reparse + delete this._names; + }), + + cssText: attribute( + function() { + // XXX: this is a CSSStyleDeclaration for an element. + // A different impl might be necessary for a set of styles + // associated returned by getComputedStyle(), e.g. + return this._element.getAttribute("style"); + }, + function(value) { + // XXX: I should parse and serialize the value to + // normalize it and remove errors. FF and chrome do that. + this._element.setAttribute("style", value); + } + ), + + length: attribute(function() { + if (!this._names) + this._names = Object.getOwnPropertyNames(this._parsed); + return this._names.length; + }), + + item: constant(function(n) { + if (!this._names) + this._names = Object.getOwnPropertyNames(this._parsed); + return this._names[n]; + }), + + getPropertyValue: constant(function(property) { + return this._parsed[toLowerCase(property)]; + }), + + // XXX: for now we ignore !important declarations + getPropertyPriority: constant(function(property) { + return ""; + }), + + // XXX the priority argument is ignored for now + setProperty: constant(function(property, value, priority) { + property = toLowerCase(property); + if (value === "") { + this.removeProperty(property); + return; + } + + // XXX are there other legal priority values? + if (priority !== undefined && priority !== "important") + return; + + // We don't just accept the property value. Instead + // we parse it to ensure that it is something valid. + // If it contains a semicolon it is invalid + if (value.indexOf(";") !== -1) return; + + var props = parseStyles(property + ":" + value); + var newvalue = props[property]; + // If there is no value now, it wasn't valid + if (!newvalue) return; + + var styles = this._parsed; + + // If the value didn't change, return without doing anything. + var oldvalue = styles[property]; + if (newvalue === oldvalue) return; + + styles[property] = value; + + // Serialize and update cssText and element.style! + this._serialize(); + }), + + removeProperty: constant(function(property) { + property = toLowerCase(property); + var styles = this._parsed; + if (property in styles) { + delete styles[property]; + + // Serialize and update cssText and element.style! + this._serialize(); + } + }), + }); + + var cssProperties = { + background: "background", + backgroundAttachment: "background-attachment", + backgroundColor: "background-color", + backgroundImage: "background-image", + backgroundPosition: "background-position", + backgroundRepeat: "background-repeat", + border: "border", + borderCollapse: "border-collapse", + borderColor: "border-color", + borderSpacing: "border-spacing", + borderStyle: "border-style", + borderTop: "border-top", + borderRight: "border-right", + borderBottom: "border-bottom", + borderLeft: "border-left", + borderTopColor: "border-top-color", + borderRightColor: "border-right-color", + borderBottomColor: "border-bottom-color", + borderLeftColor: "border-left-color", + borderTopStyle: "border-top-style", + borderRightStyle: "border-right-style", + borderBottomStyle: "border-bottom-style", + borderLeftStyle: "border-left-style", + borderTopWidth: "border-top-width", + borderRightWidth: "border-right-width", + borderBottomWidth: "border-bottom-width", + borderLeftWidth: "border-left-width", + borderWidth: "border-width", + bottom: "bottom", + captionSide: "caption-side", + clear: "clear", + clip: "clip", + color: "color", + content: "content", + counterIncrement: "counter-increment", + counterReset: "counter-reset", + cursor: "cursor", + direction: "direction", + display: "display", + emptyCells: "empty-cells", + cssFloat: "float", + font: "font", + fontFamily: "font-family", + fontSize: "font-size", + fontSizeAdjust: "font-size-adjust", + fontStretch: "font-stretch", + fontStyle: "font-style", + fontVariant: "font-variant", + fontWeight: "font-weight", + height: "height", + left: "left", + letterSpacing: "letter-spacing", + lineHeight: "line-height", + listStyle: "list-style", + listStyleImage: "list-style-image", + listStylePosition: "list-style-position", + listStyleType: "list-style-type", + margin: "margin", + marginTop: "margin-top", + marginRight: "margin-right", + marginBottom: "margin-bottom", + marginLeft: "margin-left", + markerOffset: "marker-offset", + marks: "marks", + maxHeight: "max-height", + maxWidth: "max-width", + minHeight: "min-height", + minWidth: "min-width", + opacity: "opacity", + orphans: "orphans", + outline: "outline", + outlineColor: "outline-color", + outlineStyle: "outline-style", + outlineWidth: "outline-width", + overflow: "overflow", + padding: "padding", + paddingTop: "padding-top", + paddingRight: "padding-right", + paddingBottom: "padding-bottom", + paddingLeft: "padding-left", + page: "page", + pageBreakAfter: "page-break-after", + pageBreakBefore: "page-break-before", + pageBreakInside: "page-break-inside", + position: "position", + quotes: "quotes", + right: "right", + size: "size", + tableLayout: "table-layout", + textAlign: "text-align", + textDecoration: "text-decoration", + textIndent: "text-indent", + textShadow: "text-shadow", + textTransform: "text-transform", + top: "top", + unicodeBidi: "unicode-bidi", + verticalAlign: "vertical-align", + visibility: "visibility", + whiteSpace: "white-space", + widows: "widows", + width: "width", + wordSpacing: "word-spacing", + zIndex: "z-index", + }; + + for(var prop in cssProperties) defineStyleProperty(prop); + + function defineStyleProperty(jsname) { + var cssname = cssProperties[jsname]; + Object.defineProperty(CSSStyleDeclaration.prototype, jsname, { + get: function() { + return this.getPropertyValue(cssname); + }, + set: function(value) { + if (value === "" || value == null) { // XXX? + this.removeProperty(cssname); + } + else { + // XXX Handle important declarations here! + this.setProperty(cssname, value); + } + } + }); + } + + return CSSStyleDeclaration; +}); + + +/************************************************************************ + * src/impl/cssparser.js + ************************************************************************/ + +//@line 1 "src/impl/cssparser.js" +/*! +Parser-Lib +Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. + +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. + +*/ +/* Build time: 29-November-2012 03:43:26 */ +var parserlib = {}; +(function(){ + +/** + * A generic base to inherit from for any object + * that needs event handling. + * @class EventTarget + * @constructor + */ +function EventTarget(){ + + /** + * The array of listeners for various events. + * @type Object + * @property _listeners + * @private + */ + this._listeners = {}; +} + +EventTarget.prototype = { + + //restore constructor + constructor: EventTarget, + + /** + * Adds a listener for a given event type. + * @param {String} type The type of event to add a listener for. + * @param {Function} listener The function to call when the event occurs. + * @return {void} + * @method addListener + */ + addListener: function(type, listener){ + if (!this._listeners[type]){ + this._listeners[type] = []; + } + + this._listeners[type].push(listener); + }, + + /** + * Fires an event based on the passed-in object. + * @param {Object|String} event An object with at least a 'type' attribute + * or a string indicating the event name. + * @return {void} + * @method fire + */ + fire: function(event){ + if (typeof event == "string"){ + event = { type: event }; + } + if (typeof event.target != "undefined"){ + event.target = this; + } + + if (typeof event.type == "undefined"){ + throw new Error("Event object missing 'type' property."); + } + + if (this._listeners[event.type]){ + + //create a copy of the array and use that so listeners can't chane + var listeners = this._listeners[event.type].concat(); + for (var i=0, len=listeners.length; i < len; i++){ + listeners[i].call(this, event); + } + } + }, + + /** + * Removes a listener for a given event type. + * @param {String} type The type of event to remove a listener from. + * @param {Function} listener The function to remove from the event. + * @return {void} + * @method removeListener + */ + removeListener: function(type, listener){ + if (this._listeners[type]){ + var listeners = this._listeners[type]; + for (var i=0, len=listeners.length; i < len; i++){ + if (listeners[i] === listener){ + listeners.splice(i, 1); + break; + } + } + + + } + } +}; +/** + * Convenient way to read through strings. + * @namespace parserlib.util + * @class StringReader + * @constructor + * @param {String} text The text to read. + */ +function StringReader(text){ + + /** + * The input text with line endings normalized. + * @property _input + * @type String + * @private + */ + this._input = text.replace(/\n\r?/g, "\n"); + + + /** + * The row for the character to be read next. + * @property _line + * @type int + * @private + */ + this._line = 1; + + + /** + * The column for the character to be read next. + * @property _col + * @type int + * @private + */ + this._col = 1; + + /** + * The index of the character in the input to be read next. + * @property _cursor + * @type int + * @private + */ + this._cursor = 0; +} + +StringReader.prototype = { + + //restore constructor + constructor: StringReader, + + //------------------------------------------------------------------------- + // Position info + //------------------------------------------------------------------------- + + /** + * Returns the column of the character to be read next. + * @return {int} The column of the character to be read next. + * @method getCol + */ + getCol: function(){ + return this._col; + }, + + /** + * Returns the row of the character to be read next. + * @return {int} The row of the character to be read next. + * @method getLine + */ + getLine: function(){ + return this._line ; + }, + + /** + * Determines if you're at the end of the input. + * @return {Boolean} True if there's no more input, false otherwise. + * @method eof + */ + eof: function(){ + return (this._cursor == this._input.length); + }, + + //------------------------------------------------------------------------- + // Basic reading + //------------------------------------------------------------------------- + + /** + * Reads the next character without advancing the cursor. + * @param {int} count How many characters to look ahead (default is 1). + * @return {String} The next character or null if there is no next character. + * @method peek + */ + peek: function(count){ + var c = null; + count = (typeof count == "undefined" ? 1 : count); + + //if we're not at the end of the input... + if (this._cursor < this._input.length){ + + //get character and increment cursor and column + c = this._input.charAt(this._cursor + count - 1); + } + + return c; + }, + + /** + * Reads the next character from the input and adjusts the row and column + * accordingly. + * @return {String} The next character or null if there is no next character. + * @method read + */ + read: function(){ + var c = null; + + //if we're not at the end of the input... + if (this._cursor < this._input.length){ + + //if the last character was a newline, increment row count + //and reset column count + if (this._input.charAt(this._cursor) == "\n"){ + this._line++; + this._col=1; + } else { + this._col++; + } + + //get character and increment cursor and column + c = this._input.charAt(this._cursor++); + } + + return c; + }, + + //------------------------------------------------------------------------- + // Misc + //------------------------------------------------------------------------- + + /** + * Saves the current location so it can be returned to later. + * @method mark + * @return {void} + */ + mark: function(){ + this._bookmark = { + cursor: this._cursor, + line: this._line, + col: this._col + }; + }, + + reset: function(){ + if (this._bookmark){ + this._cursor = this._bookmark.cursor; + this._line = this._bookmark.line; + this._col = this._bookmark.col; + delete this._bookmark; + } + }, + + //------------------------------------------------------------------------- + // Advanced reading + //------------------------------------------------------------------------- + + /** + * Reads up to and including the given string. Throws an error if that + * string is not found. + * @param {String} pattern The string to read. + * @return {String} The string when it is found. + * @throws Error when the string pattern is not found. + * @method readTo + */ + readTo: function(pattern){ + + var buffer = "", + c; + + /* + * First, buffer must be the same length as the pattern. + * Then, buffer must end with the pattern or else reach the + * end of the input. + */ + while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){ + c = this.read(); + if (c){ + buffer += c; + } else { + throw new Error("Expected \"" + pattern + "\" at line " + this._line + ", col " + this._col + "."); + } + } + + return buffer; + + }, + + /** + * Reads characters while each character causes the given + * filter function to return true. The function is passed + * in each character and either returns true to continue + * reading or false to stop. + * @param {Function} filter The function to read on each character. + * @return {String} The string made up of all characters that passed the + * filter check. + * @method readWhile + */ + readWhile: function(filter){ + + var buffer = "", + c = this.read(); + + while(c !== null && filter(c)){ + buffer += c; + c = this.read(); + } + + return buffer; + + }, + + /** + * Reads characters that match either text or a regular expression and + * returns those characters. If a match is found, the row and column + * are adjusted; if no match is found, the reader's state is unchanged. + * reading or false to stop. + * @param {String|RegExp} matchter If a string, then the literal string + * value is searched for. If a regular expression, then any string + * matching the pattern is search for. + * @return {String} The string made up of all characters that matched or + * null if there was no match. + * @method readMatch + */ + readMatch: function(matcher){ + + var source = this._input.substring(this._cursor), + value = null; + + //if it's a string, just do a straight match + if (typeof matcher == "string"){ + if (source.indexOf(matcher) === 0){ + value = this.readCount(matcher.length); + } + } else if (matcher instanceof RegExp){ + if (matcher.test(source)){ + value = this.readCount(RegExp.lastMatch.length); + } + } + + return value; + }, + + + /** + * Reads a given number of characters. If the end of the input is reached, + * it reads only the remaining characters and does not throw an error. + * @param {int} count The number of characters to read. + * @return {String} The string made up the read characters. + * @method readCount + */ + readCount: function(count){ + var buffer = ""; + + while(count--){ + buffer += this.read(); + } + + return buffer; + } + +}; +/** + * Type to use when a syntax error occurs. + * @class SyntaxError + * @namespace parserlib.util + * @constructor + * @param {String} message The error message. + * @param {int} line The line at which the error occurred. + * @param {int} col The column at which the error occurred. + */ +function SyntaxError(message, line, col){ + + /** + * The column at which the error occurred. + * @type int + * @property col + */ + this.col = col; + + /** + * The line at which the error occurred. + * @type int + * @property line + */ + this.line = line; + + /** + * The text representation of the unit. + * @type String + * @property text + */ + this.message = message; + +} + +//inherit from Error +SyntaxError.prototype = new Error(); +/** + * Base type to represent a single syntactic unit. + * @class SyntaxUnit + * @namespace parserlib.util + * @constructor + * @param {String} text The text of the unit. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function SyntaxUnit(text, line, col, type){ + + + /** + * The column of text on which the unit resides. + * @type int + * @property col + */ + this.col = col; + + /** + * The line of text on which the unit resides. + * @type int + * @property line + */ + this.line = line; + + /** + * The text representation of the unit. + * @type String + * @property text + */ + this.text = text; + + /** + * The type of syntax unit. + * @type int + * @property type + */ + this.type = type; +} + +/** + * Create a new syntax unit based solely on the given token. + * Convenience method for creating a new syntax unit when + * it represents a single token instead of multiple. + * @param {Object} token The token object to represent. + * @return {parserlib.util.SyntaxUnit} The object representing the token. + * @static + * @method fromToken + */ +SyntaxUnit.fromToken = function(token){ + return new SyntaxUnit(token.value, token.startLine, token.startCol); +}; + +SyntaxUnit.prototype = { + + //restore constructor + constructor: SyntaxUnit, + + /** + * Returns the text representation of the unit. + * @return {String} The text representation of the unit. + * @method valueOf + */ + valueOf: function(){ + return this.toString(); + }, + + /** + * Returns the text representation of the unit. + * @return {String} The text representation of the unit. + * @method toString + */ + toString: function(){ + return this.text; + } + +}; +/** + * Generic TokenStream providing base functionality. + * @class TokenStreamBase + * @namespace parserlib.util + * @constructor + * @param {String|StringReader} input The text to tokenize or a reader from + * which to read the input. + */ +function TokenStreamBase(input, tokenData){ + + /** + * The string reader for easy access to the text. + * @type StringReader + * @property _reader + * @private + */ + //this._reader = (typeof input == "string") ? new StringReader(input) : input; + this._reader = input ? new StringReader(input.toString()) : null; + + /** + * Token object for the last consumed token. + * @type Token + * @property _token + * @private + */ + this._token = null; + + /** + * The array of token information. + * @type Array + * @property _tokenData + * @private + */ + this._tokenData = tokenData; + + /** + * Lookahead token buffer. + * @type Array + * @property _lt + * @private + */ + this._lt = []; + + /** + * Lookahead token buffer index. + * @type int + * @property _ltIndex + * @private + */ + this._ltIndex = 0; + + this._ltIndexCache = []; +} + +/** + * Accepts an array of token information and outputs + * an array of token data containing key-value mappings + * and matching functions that the TokenStream needs. + * @param {Array} tokens An array of token descriptors. + * @return {Array} An array of processed token data. + * @method createTokenData + * @static + */ +TokenStreamBase.createTokenData = function(tokens){ + + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; + + tokenData.UNKNOWN = -1; + tokenData.unshift({name:"EOF"}); + + for (; i < len; i++){ + nameMap.push(tokenData[i].name); + tokenData[tokenData[i].name] = i; + if (tokenData[i].text){ + typeMap[tokenData[i].text] = i; + } + } + + tokenData.name = function(tt){ + return nameMap[tt]; + }; + + tokenData.type = function(c){ + return typeMap[c]; + }; + + return tokenData; +}; + +TokenStreamBase.prototype = { + + //restore constructor + constructor: TokenStreamBase, + + //------------------------------------------------------------------------- + // Matching methods + //------------------------------------------------------------------------- + + /** + * Determines if the next token matches the given token type. + * If so, that token is consumed; if not, the token is placed + * back onto the token stream. You can pass in any number of + * token types and this will return true if any of the token + * types is found. + * @param {int|int[]} tokenTypes Either a single token type or an array of + * token types that the next token might be. If an array is passed, + * it's assumed that the token can be any of these. + * @param {variant} channel (Optional) The channel to read from. If not + * provided, reads from the default (unnamed) channel. + * @return {Boolean} True if the token type matches, false if not. + * @method match + */ + match: function(tokenTypes, channel){ + + //always convert to an array, makes things easier + if (!(tokenTypes instanceof Array)){ + tokenTypes = [tokenTypes]; + } + + var tt = this.get(channel), + i = 0, + len = tokenTypes.length; + + while(i < len){ + if (tt == tokenTypes[i++]){ + return true; + } + } + + //no match found, put the token back + this.unget(); + return false; + }, + + /** + * Determines if the next token matches the given token type. + * If so, that token is consumed; if not, an error is thrown. + * @param {int|int[]} tokenTypes Either a single token type or an array of + * token types that the next token should be. If an array is passed, + * it's assumed that the token must be one of these. + * @param {variant} channel (Optional) The channel to read from. If not + * provided, reads from the default (unnamed) channel. + * @return {void} + * @method mustMatch + */ + mustMatch: function(tokenTypes, channel){ + + var token; + + //always convert to an array, makes things easier + if (!(tokenTypes instanceof Array)){ + tokenTypes = [tokenTypes]; + } + + if (!this.match.apply(this, arguments)){ + token = this.LT(1); + throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name + + " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + } + }, + + //------------------------------------------------------------------------- + // Consuming methods + //------------------------------------------------------------------------- + + /** + * Keeps reading from the token stream until either one of the specified + * token types is found or until the end of the input is reached. + * @param {int|int[]} tokenTypes Either a single token type or an array of + * token types that the next token should be. If an array is passed, + * it's assumed that the token must be one of these. + * @param {variant} channel (Optional) The channel to read from. If not + * provided, reads from the default (unnamed) channel. + * @return {void} + * @method advance + */ + advance: function(tokenTypes, channel){ + + while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){ + this.get(); + } + + return this.LA(0); + }, + + /** + * Consumes the next token from the token stream. + * @return {int} The token type of the token that was just consumed. + * @method get + */ + get: function(channel){ + + var tokenInfo = this._tokenData, + reader = this._reader, + value, + i =0, + len = tokenInfo.length, + found = false, + token, + info; + + //check the lookahead buffer first + if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){ + + i++; + this._token = this._lt[this._ltIndex++]; + info = tokenInfo[this._token.type]; + + //obey channels logic + while((info.channel !== undefined && channel !== info.channel) && + this._ltIndex < this._lt.length){ + this._token = this._lt[this._ltIndex++]; + info = tokenInfo[this._token.type]; + i++; + } + + //here be dragons + if ((info.channel === undefined || channel === info.channel) && + this._ltIndex <= this._lt.length){ + this._ltIndexCache.push(i); + return this._token.type; + } + } + + //call token retriever method + token = this._getToken(); + + //if it should be hidden, don't save a token + if (token.type > -1 && !tokenInfo[token.type].hide){ + + //apply token channel + token.channel = tokenInfo[token.type].channel; + + //save for later + this._token = token; + this._lt.push(token); + + //save space that will be moved (must be done before array is truncated) + this._ltIndexCache.push(this._lt.length - this._ltIndex + i); + + //keep the buffer under 5 items + if (this._lt.length > 5){ + this._lt.shift(); + } + + //also keep the shift buffer under 5 items + if (this._ltIndexCache.length > 5){ + this._ltIndexCache.shift(); + } + + //update lookahead index + this._ltIndex = this._lt.length; + } + + /* + * Skip to the next token if: + * 1. The token type is marked as hidden. + * 2. The token type has a channel specified and it isn't the current channel. + */ + info = tokenInfo[token.type]; + if (info && + (info.hide || + (info.channel !== undefined && channel !== info.channel))){ + return this.get(channel); + } else { + //return just the type + return token.type; + } + }, + + /** + * Looks ahead a certain number of tokens and returns the token type at + * that position. This will throw an error if you lookahead past the + * end of input, past the size of the lookahead buffer, or back past + * the first token in the lookahead buffer. + * @param {int} The index of the token type to retrieve. 0 for the + * current token, 1 for the next, -1 for the previous, etc. + * @return {int} The token type of the token in the given position. + * @method LA + */ + LA: function(index){ + var total = index, + tt; + if (index > 0){ + //TODO: Store 5 somewhere + if (index > 5){ + throw new Error("Too much lookahead."); + } + + //get all those tokens + while(total){ + tt = this.get(); + total--; + } + + //unget all those tokens + while(total < index){ + this.unget(); + total++; + } + } else if (index < 0){ + + if(this._lt[this._ltIndex+index]){ + tt = this._lt[this._ltIndex+index].type; + } else { + throw new Error("Too much lookbehind."); + } + + } else { + tt = this._token.type; + } + + return tt; + + }, + + /** + * Looks ahead a certain number of tokens and returns the token at + * that position. This will throw an error if you lookahead past the + * end of input, past the size of the lookahead buffer, or back past + * the first token in the lookahead buffer. + * @param {int} The index of the token type to retrieve. 0 for the + * current token, 1 for the next, -1 for the previous, etc. + * @return {Object} The token of the token in the given position. + * @method LA + */ + LT: function(index){ + + //lookahead first to prime the token buffer + this.LA(index); + + //now find the token, subtract one because _ltIndex is already at the next index + return this._lt[this._ltIndex+index-1]; + }, + + /** + * Returns the token type for the next token in the stream without + * consuming it. + * @return {int} The token type of the next token in the stream. + * @method peek + */ + peek: function(){ + return this.LA(1); + }, + + /** + * Returns the actual token object for the last consumed token. + * @return {Token} The token object for the last consumed token. + * @method token + */ + token: function(){ + return this._token; + }, + + /** + * Returns the name of the token for the given token type. + * @param {int} tokenType The type of token to get the name of. + * @return {String} The name of the token or "UNKNOWN_TOKEN" for any + * invalid token type. + * @method tokenName + */ + tokenName: function(tokenType){ + if (tokenType < 0 || tokenType > this._tokenData.length){ + return "UNKNOWN_TOKEN"; + } else { + return this._tokenData[tokenType].name; + } + }, + + /** + * Returns the token type value for the given token name. + * @param {String} tokenName The name of the token whose value should be returned. + * @return {int} The token type value for the given token name or -1 + * for an unknown token. + * @method tokenName + */ + tokenType: function(tokenName){ + return this._tokenData[tokenName] || -1; + }, + + /** + * Returns the last consumed token to the token stream. + * @method unget + */ + unget: function(){ + //if (this._ltIndex > -1){ + if (this._ltIndexCache.length){ + this._ltIndex -= this._ltIndexCache.pop();//--; + this._token = this._lt[this._ltIndex - 1]; + } else { + throw new Error("Too much lookahead."); + } + } + +}; + + +parserlib.util = { +StringReader: StringReader, +SyntaxError : SyntaxError, +SyntaxUnit : SyntaxUnit, +EventTarget : EventTarget, +TokenStreamBase : TokenStreamBase +}; +})(); +/* +Parser-Lib +Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. + +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. + +*/ +/* Build time: 29-November-2012 03:43:26 */ +(function(){ +var EventTarget = parserlib.util.EventTarget, +TokenStreamBase = parserlib.util.TokenStreamBase, +StringReader = parserlib.util.StringReader, +SyntaxError = parserlib.util.SyntaxError, +SyntaxUnit = parserlib.util.SyntaxUnit; + +var Colors = { + aliceblue :"#f0f8ff", + antiquewhite :"#faebd7", + aqua :"#00ffff", + aquamarine :"#7fffd4", + azure :"#f0ffff", + beige :"#f5f5dc", + bisque :"#ffe4c4", + black :"#000000", + blanchedalmond :"#ffebcd", + blue :"#0000ff", + blueviolet :"#8a2be2", + brown :"#a52a2a", + burlywood :"#deb887", + cadetblue :"#5f9ea0", + chartreuse :"#7fff00", + chocolate :"#d2691e", + coral :"#ff7f50", + cornflowerblue :"#6495ed", + cornsilk :"#fff8dc", + crimson :"#dc143c", + cyan :"#00ffff", + darkblue :"#00008b", + darkcyan :"#008b8b", + darkgoldenrod :"#b8860b", + darkgray :"#a9a9a9", + darkgreen :"#006400", + darkkhaki :"#bdb76b", + darkmagenta :"#8b008b", + darkolivegreen :"#556b2f", + darkorange :"#ff8c00", + darkorchid :"#9932cc", + darkred :"#8b0000", + darksalmon :"#e9967a", + darkseagreen :"#8fbc8f", + darkslateblue :"#483d8b", + darkslategray :"#2f4f4f", + darkturquoise :"#00ced1", + darkviolet :"#9400d3", + deeppink :"#ff1493", + deepskyblue :"#00bfff", + dimgray :"#696969", + dodgerblue :"#1e90ff", + firebrick :"#b22222", + floralwhite :"#fffaf0", + forestgreen :"#228b22", + fuchsia :"#ff00ff", + gainsboro :"#dcdcdc", + ghostwhite :"#f8f8ff", + gold :"#ffd700", + goldenrod :"#daa520", + gray :"#808080", + green :"#008000", + greenyellow :"#adff2f", + honeydew :"#f0fff0", + hotpink :"#ff69b4", + indianred :"#cd5c5c", + indigo :"#4b0082", + ivory :"#fffff0", + khaki :"#f0e68c", + lavender :"#e6e6fa", + lavenderblush :"#fff0f5", + lawngreen :"#7cfc00", + lemonchiffon :"#fffacd", + lightblue :"#add8e6", + lightcoral :"#f08080", + lightcyan :"#e0ffff", + lightgoldenrodyellow :"#fafad2", + lightgrey :"#d3d3d3", + lightgreen :"#90ee90", + lightpink :"#ffb6c1", + lightsalmon :"#ffa07a", + lightseagreen :"#20b2aa", + lightskyblue :"#87cefa", + lightslategray :"#778899", + lightsteelblue :"#b0c4de", + lightyellow :"#ffffe0", + lime :"#00ff00", + limegreen :"#32cd32", + linen :"#faf0e6", + magenta :"#ff00ff", + maroon :"#800000", + mediumaquamarine:"#66cdaa", + mediumblue :"#0000cd", + mediumorchid :"#ba55d3", + mediumpurple :"#9370d8", + mediumseagreen :"#3cb371", + mediumslateblue :"#7b68ee", + mediumspringgreen :"#00fa9a", + mediumturquoise :"#48d1cc", + mediumvioletred :"#c71585", + midnightblue :"#191970", + mintcream :"#f5fffa", + mistyrose :"#ffe4e1", + moccasin :"#ffe4b5", + navajowhite :"#ffdead", + navy :"#000080", + oldlace :"#fdf5e6", + olive :"#808000", + olivedrab :"#6b8e23", + orange :"#ffa500", + orangered :"#ff4500", + orchid :"#da70d6", + palegoldenrod :"#eee8aa", + palegreen :"#98fb98", + paleturquoise :"#afeeee", + palevioletred :"#d87093", + papayawhip :"#ffefd5", + peachpuff :"#ffdab9", + peru :"#cd853f", + pink :"#ffc0cb", + plum :"#dda0dd", + powderblue :"#b0e0e6", + purple :"#800080", + red :"#ff0000", + rosybrown :"#bc8f8f", + royalblue :"#4169e1", + saddlebrown :"#8b4513", + salmon :"#fa8072", + sandybrown :"#f4a460", + seagreen :"#2e8b57", + seashell :"#fff5ee", + sienna :"#a0522d", + silver :"#c0c0c0", + skyblue :"#87ceeb", + slateblue :"#6a5acd", + slategray :"#708090", + snow :"#fffafa", + springgreen :"#00ff7f", + steelblue :"#4682b4", + tan :"#d2b48c", + teal :"#008080", + thistle :"#d8bfd8", + tomato :"#ff6347", + turquoise :"#40e0d0", + violet :"#ee82ee", + wheat :"#f5deb3", + white :"#ffffff", + whitesmoke :"#f5f5f5", + yellow :"#ffff00", + yellowgreen :"#9acd32" +}; +/** + * Represents a selector combinator (whitespace, +, >). + * @namespace parserlib.css + * @class Combinator + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {String} text The text representation of the unit. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function Combinator(text, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); + + /** + * The type of modifier. + * @type String + * @property type + */ + this.type = "unknown"; + + //pretty simple + if (/^\s+$/.test(text)){ + this.type = "descendant"; + } else if (text == ">"){ + this.type = "child"; + } else if (text == "+"){ + this.type = "adjacent-sibling"; + } else if (text == "~"){ + this.type = "sibling"; + } + +} + +Combinator.prototype = new SyntaxUnit(); +Combinator.prototype.constructor = Combinator; + +/** + * Represents a media feature, such as max-width:500. + * @namespace parserlib.css + * @class MediaFeature + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {SyntaxUnit} name The name of the feature. + * @param {SyntaxUnit} value The value of the feature or null if none. + */ +function MediaFeature(name, value){ + + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); + + /** + * The name of the media feature + * @type String + * @property name + */ + this.name = name; + + /** + * The value for the feature or null if there is none. + * @type SyntaxUnit + * @property value + */ + this.value = value; +} + +MediaFeature.prototype = new SyntaxUnit(); +MediaFeature.prototype.constructor = MediaFeature; + +/** + * Represents an individual media query. + * @namespace parserlib.css + * @class MediaQuery + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {String} modifier The modifier "not" or "only" (or null). + * @param {String} mediaType The type of media (i.e., "print"). + * @param {Array} parts Array of selectors parts making up this selector. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function MediaQuery(modifier, mediaType, features, line, col){ + + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); + + /** + * The media modifier ("not" or "only") + * @type String + * @property modifier + */ + this.modifier = modifier; + + /** + * The mediaType (i.e., "print") + * @type String + * @property mediaType + */ + this.mediaType = mediaType; + + /** + * The parts that make up the selector. + * @type Array + * @property features + */ + this.features = features; + +} + +MediaQuery.prototype = new SyntaxUnit(); +MediaQuery.prototype.constructor = MediaQuery; + +/** + * A CSS3 parser. + * @namespace parserlib.css + * @class Parser + * @constructor + * @param {Object} options (Optional) Various options for the parser: + * starHack (true|false) to allow IE6 star hack as valid, + * underscoreHack (true|false) to interpret leading underscores + * as IE6-7 targeting for known properties, ieFilters (true|false) + * to indicate that IE < 8 filters should be accepted and not throw + * syntax errors. + */ +function Parser(options){ + + //inherit event functionality + EventTarget.call(this); + + + this.options = options || {}; + + this._tokenStream = null; +} + +//Static constants +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + +Parser.prototype = function(){ + + var proto = new EventTarget(), //new prototype + prop, + additions = { + + //restore constructor + constructor: Parser, + + //instance constants - yuck + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, + + //----------------------------------------------------------------- + // Grammar + //----------------------------------------------------------------- + + _stylesheet: function(){ + + /* + * stylesheet + * : [ CHARSET_SYM S* STRING S* ';' ]? + * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* + * [ namespace [S|CDO|CDC]* ]* + * [ [ ruleset | media | page | font_face | keyframes ] [S|CDO|CDC]* ]* + * ; + */ + + var tokenStream = this._tokenStream, + charset = null, + token, + tt; + + this.fire("startstylesheet"); + + //try to read character set + this._charset(); + + this._skipCruft(); + + //try to read imports - may be more than one + while (tokenStream.peek() == Tokens.IMPORT_SYM){ + this._import(); + this._skipCruft(); + } + + //try to read namespaces - may be more than one + while (tokenStream.peek() == Tokens.NAMESPACE_SYM){ + this._namespace(); + this._skipCruft(); + } + + //get the next token + tt = tokenStream.peek(); + + //try to read the rest + while(tt > Tokens.EOF){ + + try { + + switch(tt){ + case Tokens.MEDIA_SYM: + this._media(); + this._skipCruft(); + break; + case Tokens.PAGE_SYM: + this._page(); + this._skipCruft(); + break; + case Tokens.FONT_FACE_SYM: + this._font_face(); + this._skipCruft(); + break; + case Tokens.KEYFRAMES_SYM: + this._keyframes(); + this._skipCruft(); + break; + case Tokens.S: + this._readWhitespace(); + break; + default: + if(!this._ruleset()){ + + //error handling for known issues + switch(tt){ + case Tokens.CHARSET_SYM: + token = tokenStream.LT(1); + this._charset(false); + throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol); + case Tokens.IMPORT_SYM: + token = tokenStream.LT(1); + this._import(false); + throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol); + case Tokens.NAMESPACE_SYM: + token = tokenStream.LT(1); + this._namespace(false); + throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol); + default: + tokenStream.get(); //get the last token + this._unexpectedToken(tokenStream.token()); + } + + } + } + } catch(ex) { + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + } else { + throw ex; + } + } + + tt = tokenStream.peek(); + } + + if (tt != Tokens.EOF){ + this._unexpectedToken(tokenStream.token()); + } + + this.fire("endstylesheet"); + }, + + _charset: function(emit){ + var tokenStream = this._tokenStream, + charset, + token, + line, + col; + + if (tokenStream.match(Tokens.CHARSET_SYM)){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.STRING); + + token = tokenStream.token(); + charset = token.value; + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.SEMICOLON); + + if (emit !== false){ + this.fire({ + type: "charset", + charset:charset, + line: line, + col: col + }); + } + } + }, + + _import: function(emit){ + /* + * import + * : IMPORT_SYM S* + * [STRING|URI] S* media_query_list? ';' S* + */ + + var tokenStream = this._tokenStream, + tt, + uri, + importToken, + mediaList = []; + + //read import symbol + tokenStream.mustMatch(Tokens.IMPORT_SYM); + importToken = tokenStream.token(); + this._readWhitespace(); + + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); + + //grab the URI value + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); + + this._readWhitespace(); + + mediaList = this._media_query_list(); + + //must end with a semicolon + tokenStream.mustMatch(Tokens.SEMICOLON); + this._readWhitespace(); + + if (emit !== false){ + this.fire({ + type: "import", + uri: uri, + media: mediaList, + line: importToken.startLine, + col: importToken.startCol + }); + } + + }, + + _namespace: function(emit){ + /* + * namespace + * : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S* + */ + + var tokenStream = this._tokenStream, + line, + col, + prefix, + uri; + + //read import symbol + tokenStream.mustMatch(Tokens.NAMESPACE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + this._readWhitespace(); + + //it's a namespace prefix - no _namespace_prefix() method because it's just an IDENT + if (tokenStream.match(Tokens.IDENT)){ + prefix = tokenStream.token().value; + this._readWhitespace(); + } + + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); + /*if (!tokenStream.match(Tokens.STRING)){ + tokenStream.mustMatch(Tokens.URI); + }*/ + + //grab the URI value + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); + + this._readWhitespace(); + + //must end with a semicolon + tokenStream.mustMatch(Tokens.SEMICOLON); + this._readWhitespace(); + + if (emit !== false){ + this.fire({ + type: "namespace", + prefix: prefix, + uri: uri, + line: line, + col: col + }); + } + + }, + + _media: function(){ + /* + * media + * : MEDIA_SYM S* media_query_list S* '{' S* ruleset* '}' S* + * ; + */ + var tokenStream = this._tokenStream, + line, + col, + mediaList;// = []; + + //look for @media + tokenStream.mustMatch(Tokens.MEDIA_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + mediaList = this._media_query_list(); + + tokenStream.mustMatch(Tokens.LBRACE); + this._readWhitespace(); + + this.fire({ + type: "startmedia", + media: mediaList, + line: line, + col: col + }); + + while(true) { + if (tokenStream.peek() == Tokens.PAGE_SYM){ + this._page(); + } else if (!this._ruleset()){ + break; + } + } + + tokenStream.mustMatch(Tokens.RBRACE); + this._readWhitespace(); + + this.fire({ + type: "endmedia", + media: mediaList, + line: line, + col: col + }); + }, + + + //CSS3 Media Queries + _media_query_list: function(){ + /* + * media_query_list + * : S* [media_query [ ',' S* media_query ]* ]? + * ; + */ + var tokenStream = this._tokenStream, + mediaList = []; + + + this._readWhitespace(); + + if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){ + mediaList.push(this._media_query()); + } + + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + mediaList.push(this._media_query()); + } + + return mediaList; + }, + + /* + * Note: "expression" in the grammar maps to the _media_expression + * method. + + */ + _media_query: function(){ + /* + * media_query + * : [ONLY | NOT]? S* media_type S* [ AND S* expression ]* + * | expression [ AND S* expression ]* + * ; + */ + var tokenStream = this._tokenStream, + type = null, + ident = null, + token = null, + expressions = []; + + if (tokenStream.match(Tokens.IDENT)){ + ident = tokenStream.token().value.toLowerCase(); + + //since there's no custom tokens for these, need to manually check + if (ident != "only" && ident != "not"){ + tokenStream.unget(); + ident = null; + } else { + token = tokenStream.token(); + } + } + + this._readWhitespace(); + + if (tokenStream.peek() == Tokens.IDENT){ + type = this._media_type(); + if (token === null){ + token = tokenStream.token(); + } + } else if (tokenStream.peek() == Tokens.LPAREN){ + if (token === null){ + token = tokenStream.LT(1); + } + expressions.push(this._media_expression()); + } + + if (type === null && expressions.length === 0){ + return null; + } else { + this._readWhitespace(); + while (tokenStream.match(Tokens.IDENT)){ + if (tokenStream.token().value.toLowerCase() != "and"){ + this._unexpectedToken(tokenStream.token()); + } + + this._readWhitespace(); + expressions.push(this._media_expression()); + } + } + + return new MediaQuery(ident, type, expressions, token.startLine, token.startCol); + }, + + //CSS3 Media Queries + _media_type: function(){ + /* + * media_type + * : IDENT + * ; + */ + return this._media_feature(); + }, + + /** + * Note: in CSS3 Media Queries, this is called "expression". + * Renamed here to avoid conflict with CSS3 Selectors + * definition of "expression". Also note that "expr" in the + * grammar now maps to "expression" from CSS3 selectors. + * @method _media_expression + * @private + */ + _media_expression: function(){ + /* + * expression + * : '(' S* media_feature S* [ ':' S* expr ]? ')' S* + * ; + */ + var tokenStream = this._tokenStream, + feature = null, + token, + expression = null; + + tokenStream.mustMatch(Tokens.LPAREN); + + feature = this._media_feature(); + this._readWhitespace(); + + if (tokenStream.match(Tokens.COLON)){ + this._readWhitespace(); + token = tokenStream.LT(1); + expression = this._expression(); + } + + tokenStream.mustMatch(Tokens.RPAREN); + this._readWhitespace(); + + return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null)); + }, + + //CSS3 Media Queries + _media_feature: function(){ + /* + * media_feature + * : IDENT + * ; + */ + var tokenStream = this._tokenStream; + + tokenStream.mustMatch(Tokens.IDENT); + + return SyntaxUnit.fromToken(tokenStream.token()); + }, + + //CSS3 Paged Media + _page: function(){ + /* + * page: + * PAGE_SYM S* IDENT? pseudo_page? S* + * '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S* + * ; + */ + var tokenStream = this._tokenStream, + line, + col, + identifier = null, + pseudoPage = null; + + //look for @page + tokenStream.mustMatch(Tokens.PAGE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + if (tokenStream.match(Tokens.IDENT)){ + identifier = tokenStream.token().value; + + //The value 'auto' may not be used as a page name and MUST be treated as a syntax error. + if (identifier.toLowerCase() === "auto"){ + this._unexpectedToken(tokenStream.token()); + } + } + + //see if there's a colon upcoming + if (tokenStream.peek() == Tokens.COLON){ + pseudoPage = this._pseudo_page(); + } + + this._readWhitespace(); + + this.fire({ + type: "startpage", + id: identifier, + pseudo: pseudoPage, + line: line, + col: col + }); + + this._readDeclarations(true, true); + + this.fire({ + type: "endpage", + id: identifier, + pseudo: pseudoPage, + line: line, + col: col + }); + + }, + + //CSS3 Paged Media + _margin: function(){ + /* + * margin : + * margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S* + * ; + */ + var tokenStream = this._tokenStream, + line, + col, + marginSym = this._margin_sym(); + + if (marginSym){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this.fire({ + type: "startpagemargin", + margin: marginSym, + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endpagemargin", + margin: marginSym, + line: line, + col: col + }); + return true; + } else { + return false; + } + }, + + //CSS3 Paged Media + _margin_sym: function(){ + + /* + * margin_sym : + * TOPLEFTCORNER_SYM | + * TOPLEFT_SYM | + * TOPCENTER_SYM | + * TOPRIGHT_SYM | + * TOPRIGHTCORNER_SYM | + * BOTTOMLEFTCORNER_SYM | + * BOTTOMLEFT_SYM | + * BOTTOMCENTER_SYM | + * BOTTOMRIGHT_SYM | + * BOTTOMRIGHTCORNER_SYM | + * LEFTTOP_SYM | + * LEFTMIDDLE_SYM | + * LEFTBOTTOM_SYM | + * RIGHTTOP_SYM | + * RIGHTMIDDLE_SYM | + * RIGHTBOTTOM_SYM + * ; + */ + + var tokenStream = this._tokenStream; + + if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM, + Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM, + Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, + Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM, + Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, + Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM, + Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM])) + { + return SyntaxUnit.fromToken(tokenStream.token()); + } else { + return null; + } + + }, + + _pseudo_page: function(){ + /* + * pseudo_page + * : ':' IDENT + * ; + */ + + var tokenStream = this._tokenStream; + + tokenStream.mustMatch(Tokens.COLON); + tokenStream.mustMatch(Tokens.IDENT); + + //TODO: CSS3 Paged Media says only "left", "center", and "right" are allowed + + return tokenStream.token().value; + }, + + _font_face: function(){ + /* + * font_face + * : FONT_FACE_SYM S* + * '{' S* declaration [ ';' S* declaration ]* '}' S* + * ; + */ + var tokenStream = this._tokenStream, + line, + col; + + //look for @page + tokenStream.mustMatch(Tokens.FONT_FACE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + this.fire({ + type: "startfontface", + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endfontface", + line: line, + col: col + }); + }, + + _operator: function(){ + + /* + * operator + * : '/' S* | ',' S* | /( empty )/ + * ; + */ + + var tokenStream = this._tokenStream, + token = null; + + if (tokenStream.match([Tokens.SLASH, Tokens.COMMA])){ + token = tokenStream.token(); + this._readWhitespace(); + } + return token ? PropertyValuePart.fromToken(token) : null; + + }, + + _combinator: function(){ + + /* + * combinator + * : PLUS S* | GREATER S* | TILDE S* | S+ + * ; + */ + + var tokenStream = this._tokenStream, + value = null, + token; + + if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){ + token = tokenStream.token(); + value = new Combinator(token.value, token.startLine, token.startCol); + this._readWhitespace(); + } + + return value; + }, + + _unary_operator: function(){ + + /* + * unary_operator + * : '-' | '+' + * ; + */ + + var tokenStream = this._tokenStream; + + if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){ + return tokenStream.token().value; + } else { + return null; + } + }, + + _property: function(){ + + /* + * property + * : IDENT S* + * ; + */ + + var tokenStream = this._tokenStream, + value = null, + hack = null, + tokenValue, + token, + line, + col; + + //check for star hack - throws error if not allowed + if (tokenStream.peek() == Tokens.STAR && this.options.starHack){ + tokenStream.get(); + token = tokenStream.token(); + hack = token.value; + line = token.startLine; + col = token.startCol; + } + + if(tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + tokenValue = token.value; + + //check for underscore hack - no error if not allowed because it's valid CSS syntax + if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){ + hack = "_"; + tokenValue = tokenValue.substring(1); + } + + value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol)); + this._readWhitespace(); + } + + return value; + }, + + //Augmented with CSS3 Selectors + _ruleset: function(){ + /* + * ruleset + * : selectors_group + * '{' S* declaration? [ ';' S* declaration? ]* '}' S* + * ; + */ + + var tokenStream = this._tokenStream, + tt, + selectors; + + + /* + * Error Recovery: If even a single selector fails to parse, + * then the entire ruleset should be thrown away. + */ + try { + selectors = this._selectors_group(); + } catch (ex){ + if (ex instanceof SyntaxError && !this.options.strict){ + + //fire error event + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + + //skip over everything until closing brace + tt = tokenStream.advance([Tokens.RBRACE]); + if (tt == Tokens.RBRACE){ + //if there's a right brace, the rule is finished so don't do anything + } else { + //otherwise, rethrow the error because it wasn't handled properly + throw ex; + } + + } else { + //not a syntax error, rethrow it + throw ex; + } + + //trigger parser to continue + return true; + } + + //if it got here, all selectors parsed + if (selectors){ + + this.fire({ + type: "startrule", + selectors: selectors, + line: selectors[0].line, + col: selectors[0].col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endrule", + selectors: selectors, + line: selectors[0].line, + col: selectors[0].col + }); + + } + + return selectors; + + }, + + //CSS3 Selectors + _selectors_group: function(){ + + /* + * selectors_group + * : selector [ COMMA S* selector ]* + * ; + */ + var tokenStream = this._tokenStream, + selectors = [], + selector; + + selector = this._selector(); + if (selector !== null){ + + selectors.push(selector); + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + selector = this._selector(); + if (selector !== null){ + selectors.push(selector); + } else { + this._unexpectedToken(tokenStream.LT(1)); + } + } + } + + return selectors.length ? selectors : null; + }, + + //CSS3 Selectors + _selector: function(){ + /* + * selector + * : simple_selector_sequence [ combinator simple_selector_sequence ]* + * ; + */ + + var tokenStream = this._tokenStream, + selector = [], + nextSelector = null, + combinator = null, + ws = null; + + //if there's no simple selector, then there's no selector + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + return null; + } + + selector.push(nextSelector); + + do { + + //look for a combinator + combinator = this._combinator(); + + if (combinator !== null){ + selector.push(combinator); + nextSelector = this._simple_selector_sequence(); + + //there must be a next selector + if (nextSelector === null){ + this._unexpectedToken(this.LT(1)); + } else { + + //nextSelector is an instance of SelectorPart + selector.push(nextSelector); + } + } else { + + //if there's not whitespace, we're done + if (this._readWhitespace()){ + + //add whitespace separator + ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol); + + //combinator is not required + combinator = this._combinator(); + + //selector is required if there's a combinator + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + if (combinator !== null){ + this._unexpectedToken(tokenStream.LT(1)); + } + } else { + + if (combinator !== null){ + selector.push(combinator); + } else { + selector.push(ws); + } + + selector.push(nextSelector); + } + } else { + break; + } + + } + } while(true); + + return new Selector(selector, selector[0].line, selector[0].col); + }, + + //CSS3 Selectors + _simple_selector_sequence: function(){ + /* + * simple_selector_sequence + * : [ type_selector | universal ] + * [ HASH | class | attrib | pseudo | negation ]* + * | [ HASH | class | attrib | pseudo | negation ]+ + * ; + */ + + var tokenStream = this._tokenStream, + + //parts of a simple selector + elementName = null, + modifiers = [], + + //complete selector text + selectorText= "", + + //the different parts after the element name to search for + components = [ + //HASH + function(){ + return tokenStream.match(Tokens.HASH) ? + new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : + null; + }, + this._class, + this._attrib, + this._pseudo, + this._negation + ], + i = 0, + len = components.length, + component = null, + found = false, + line, + col; + + + //get starting line and column for the selector + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + + elementName = this._type_selector(); + if (!elementName){ + elementName = this._universal(); + } + + if (elementName !== null){ + selectorText += elementName; + } + + while(true){ + + //whitespace means we're done + if (tokenStream.peek() === Tokens.S){ + break; + } + + //check for each component + while(i < len && component === null){ + component = components[i++].call(this); + } + + if (component === null){ + + //we don't have a selector + if (selectorText === ""){ + return null; + } else { + break; + } + } else { + i = 0; + modifiers.push(component); + selectorText += component.toString(); + component = null; + } + } + + + return selectorText !== "" ? + new SelectorPart(elementName, modifiers, selectorText, line, col) : + null; + }, + + //CSS3 Selectors + _type_selector: function(){ + /* + * type_selector + * : [ namespace_prefix ]? element_name + * ; + */ + + var tokenStream = this._tokenStream, + ns = this._namespace_prefix(), + elementName = this._element_name(); + + if (!elementName){ + /* + * Need to back out the namespace that was read due to both + * type_selector and universal reading namespace_prefix + * first. Kind of hacky, but only way I can figure out + * right now how to not change the grammar. + */ + if (ns){ + tokenStream.unget(); + if (ns.length > 1){ + tokenStream.unget(); + } + } + + return null; + } else { + if (ns){ + elementName.text = ns + elementName.text; + elementName.col -= ns.length; + } + return elementName; + } + }, + + //CSS3 Selectors + _class: function(){ + /* + * class + * : '.' IDENT + * ; + */ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.DOT)){ + tokenStream.mustMatch(Tokens.IDENT); + token = tokenStream.token(); + return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1); + } else { + return null; + } + + }, + + //CSS3 Selectors + _element_name: function(){ + /* + * element_name + * : IDENT + * ; + */ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol); + + } else { + return null; + } + }, + + //CSS3 Selectors + _namespace_prefix: function(){ + /* + * namespace_prefix + * : [ IDENT | '*' ]? '|' + * ; + */ + var tokenStream = this._tokenStream, + value = ""; + + //verify that this is a namespace prefix + if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){ + + if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){ + value += tokenStream.token().value; + } + + tokenStream.mustMatch(Tokens.PIPE); + value += "|"; + + } + + return value.length ? value : null; + }, + + //CSS3 Selectors + _universal: function(){ + /* + * universal + * : [ namespace_prefix ]? '*' + * ; + */ + var tokenStream = this._tokenStream, + value = "", + ns; + + ns = this._namespace_prefix(); + if(ns){ + value += ns; + } + + if(tokenStream.match(Tokens.STAR)){ + value += "*"; + } + + return value.length ? value : null; + + }, + + //CSS3 Selectors + _attrib: function(){ + /* + * attrib + * : '[' S* [ namespace_prefix ]? IDENT S* + * [ [ PREFIXMATCH | + * SUFFIXMATCH | + * SUBSTRINGMATCH | + * '=' | + * INCLUDES | + * DASHMATCH ] S* [ IDENT | STRING ] S* + * ]? ']' + * ; + */ + + var tokenStream = this._tokenStream, + value = null, + ns, + token; + + if (tokenStream.match(Tokens.LBRACKET)){ + token = tokenStream.token(); + value = token.value; + value += this._readWhitespace(); + + ns = this._namespace_prefix(); + + if (ns){ + value += ns; + } + + tokenStream.mustMatch(Tokens.IDENT); + value += tokenStream.token().value; + value += this._readWhitespace(); + + if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH, + Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){ + + value += tokenStream.token().value; + value += this._readWhitespace(); + + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); + value += tokenStream.token().value; + value += this._readWhitespace(); + } + + tokenStream.mustMatch(Tokens.RBRACKET); + + return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol); + } else { + return null; + } + }, + + //CSS3 Selectors + _pseudo: function(){ + + /* + * pseudo + * : ':' ':'? [ IDENT | functional_pseudo ] + * ; + */ + + var tokenStream = this._tokenStream, + pseudo = null, + colons = ":", + line, + col; + + if (tokenStream.match(Tokens.COLON)){ + + if (tokenStream.match(Tokens.COLON)){ + colons += ":"; + } + + if (tokenStream.match(Tokens.IDENT)){ + pseudo = tokenStream.token().value; + line = tokenStream.token().startLine; + col = tokenStream.token().startCol - colons.length; + } else if (tokenStream.peek() == Tokens.FUNCTION){ + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol - colons.length; + pseudo = this._functional_pseudo(); + } + + if (pseudo){ + pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col); + } + } + + return pseudo; + }, + + //CSS3 Selectors + _functional_pseudo: function(){ + /* + * functional_pseudo + * : FUNCTION S* expression ')' + * ; + */ + + var tokenStream = this._tokenStream, + value = null; + + if(tokenStream.match(Tokens.FUNCTION)){ + value = tokenStream.token().value; + value += this._readWhitespace(); + value += this._expression(); + tokenStream.mustMatch(Tokens.RPAREN); + value += ")"; + } + + return value; + }, + + //CSS3 Selectors + _expression: function(){ + /* + * expression + * : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+ + * ; + */ + + var tokenStream = this._tokenStream, + value = ""; + + while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION, + Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH, + Tokens.FREQ, Tokens.ANGLE, Tokens.TIME, + Tokens.RESOLUTION])){ + + value += tokenStream.token().value; + value += this._readWhitespace(); + } + + return value.length ? value : null; + + }, + + //CSS3 Selectors + _negation: function(){ + /* + * negation + * : NOT S* negation_arg S* ')' + * ; + */ + + var tokenStream = this._tokenStream, + line, + col, + value = "", + arg, + subpart = null; + + if (tokenStream.match(Tokens.NOT)){ + value = tokenStream.token().value; + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + value += this._readWhitespace(); + arg = this._negation_arg(); + value += arg; + value += this._readWhitespace(); + tokenStream.match(Tokens.RPAREN); + value += tokenStream.token().value; + + subpart = new SelectorSubPart(value, "not", line, col); + subpart.args.push(arg); + } + + return subpart; + }, + + //CSS3 Selectors + _negation_arg: function(){ + /* + * negation_arg + * : type_selector | universal | HASH | class | attrib | pseudo + * ; + */ + + var tokenStream = this._tokenStream, + args = [ + this._type_selector, + this._universal, + function(){ + return tokenStream.match(Tokens.HASH) ? + new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : + null; + }, + this._class, + this._attrib, + this._pseudo + ], + arg = null, + i = 0, + len = args.length, + elementName, + line, + col, + part; + + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + + while(i < len && arg === null){ + + arg = args[i].call(this); + i++; + } + + //must be a negation arg + if (arg === null){ + this._unexpectedToken(tokenStream.LT(1)); + } + + //it's an element name + if (arg.type == "elementName"){ + part = new SelectorPart(arg, [], arg.toString(), line, col); + } else { + part = new SelectorPart(null, [arg], arg.toString(), line, col); + } + + return part; + }, + + _declaration: function(){ + + /* + * declaration + * : property ':' S* expr prio? + * | /( empty )/ + * ; + */ + + var tokenStream = this._tokenStream, + property = null, + expr = null, + prio = null, + error = null, + invalid = null; + + property = this._property(); + if (property !== null){ + + tokenStream.mustMatch(Tokens.COLON); + this._readWhitespace(); + + expr = this._expr(); + + //if there's no parts for the value, it's an error + if (!expr || expr.length === 0){ + this._unexpectedToken(tokenStream.LT(1)); + } + + prio = this._prio(); + + try { + this._validateProperty(property, expr); + } catch (ex) { + invalid = ex; + } + + this.fire({ + type: "property", + property: property, + value: expr, + important: prio, + line: property.line, + col: property.col, + invalid: invalid + }); + + return true; + } else { + return false; + } + }, + + _prio: function(){ + /* + * prio + * : IMPORTANT_SYM S* + * ; + */ + + var tokenStream = this._tokenStream, + result = tokenStream.match(Tokens.IMPORTANT_SYM); + + this._readWhitespace(); + return result; + }, + + _expr: function(){ + /* + * expr + * : term [ operator term ]* + * ; + */ + + var tokenStream = this._tokenStream, + values = [], + //valueParts = [], + value = null, + operator = null; + + value = this._term(); + if (value !== null){ + + values.push(value); + + do { + operator = this._operator(); + + //if there's an operator, keep building up the value parts + if (operator){ + values.push(operator); + } /*else { + //if there's not an operator, you have a full value + values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); + valueParts = []; + }*/ + + value = this._term(); + + if (value === null){ + break; + } else { + values.push(value); + } + } while(true); + } + + //cleanup + /*if (valueParts.length){ + values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); + }*/ + + return values.length > 0 ? new PropertyValue(values, values[0].startLine, values[0].startCol) : null; + }, + + _term: function(){ + + /* + * term + * : unary_operator? + * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | ANGLE S* | + * TIME S* | FREQ S* | function | ie_function ] + * | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor + * ; + */ + + var tokenStream = this._tokenStream, + unary = null, + value = null, + line, + col; + + //returns the operator or null + unary = this._unary_operator(); + if (unary !== null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + + //exception for IE filters + if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){ + + value = this._ie_function(); + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + + //see if there's a simple match + } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH, + Tokens.ANGLE, Tokens.TIME, + Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){ + + value = tokenStream.token().value; + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + this._readWhitespace(); + } else { + + //see if it's a color + value = this._hexcolor(); + if (value === null){ + + //if there's no unary, get the start of the next token for line/col info + if (unary === null){ + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + } + + //has to be a function + if (value === null){ + + /* + * This checks for alpha(opacity=0) style of IE + * functions. IE_FUNCTION only presents progid: style. + */ + if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){ + value = this._ie_function(); + } else { + value = this._function(); + } + } + + /*if (value === null){ + return null; + //throw new Error("Expected identifier at line " + tokenStream.token().startLine + ", character " + tokenStream.token().startCol + "."); + }*/ + + } else { + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + } + + } + + return value !== null ? + new PropertyValuePart(unary !== null ? unary + value : value, line, col) : + null; + + }, + + _function: function(){ + + /* + * function + * : FUNCTION S* expr ')' S* + * ; + */ + + var tokenStream = this._tokenStream, + functionText = null, + expr = null, + lt; + + if (tokenStream.match(Tokens.FUNCTION)){ + functionText = tokenStream.token().value; + this._readWhitespace(); + expr = this._expr(); + functionText += expr; + + //START: Horrible hack in case it's an IE filter + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + + //might be second time in the loop + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + + //functionText += this._term(); + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + //END: Horrible Hack + + tokenStream.match(Tokens.RPAREN); + functionText += ")"; + this._readWhitespace(); + } + + return functionText; + }, + + _ie_function: function(){ + + /* (My own extension) + * ie_function + * : IE_FUNCTION S* IDENT '=' term [S* ','? IDENT '=' term]+ ')' S* + * ; + */ + + var tokenStream = this._tokenStream, + functionText = null, + expr = null, + lt; + + //IE function can begin like a regular function, too + if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){ + functionText = tokenStream.token().value; + + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + + //might be second time in the loop + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + + //functionText += this._term(); + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + + tokenStream.match(Tokens.RPAREN); + functionText += ")"; + this._readWhitespace(); + } + + return functionText; + }, + + _hexcolor: function(){ + /* + * There is a constraint on the color that it must + * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) + * after the "#"; e.g., "#000" is OK, but "#abcd" is not. + * + * hexcolor + * : HASH S* + * ; + */ + + var tokenStream = this._tokenStream, + token, + color = null; + + if(tokenStream.match(Tokens.HASH)){ + + //need to do some validation here + + token = tokenStream.token(); + color = token.value; + if (!/#[a-f0-9]{3,6}/i.test(color)){ + throw new SyntaxError("Expected a hex color but found '" + color + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + } + this._readWhitespace(); + } + + return color; + }, + + //----------------------------------------------------------------- + // Animations methods + //----------------------------------------------------------------- + + _keyframes: function(){ + + /* + * keyframes: + * : KEYFRAMES_SYM S* keyframe_name S* '{' S* keyframe_rule* '}' { + * ; + */ + var tokenStream = this._tokenStream, + token, + tt, + name; + + tokenStream.mustMatch(Tokens.KEYFRAMES_SYM); + this._readWhitespace(); + name = this._keyframe_name(); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.LBRACE); + + this.fire({ + type: "startkeyframes", + name: name, + line: name.line, + col: name.col + }); + + this._readWhitespace(); + tt = tokenStream.peek(); + + //check for key + while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) { + this._keyframe_rule(); + this._readWhitespace(); + tt = tokenStream.peek(); + } + + this.fire({ + type: "endkeyframes", + name: name, + line: name.line, + col: name.col + }); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.RBRACE); + + }, + + _keyframe_name: function(){ + + /* + * keyframe_name: + * : IDENT + * | STRING + * ; + */ + var tokenStream = this._tokenStream, + token; + + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); + return SyntaxUnit.fromToken(tokenStream.token()); + }, + + _keyframe_rule: function(){ + + /* + * keyframe_rule: + * : key_list S* + * '{' S* declaration [ ';' S* declaration ]* '}' S* + * ; + */ + var tokenStream = this._tokenStream, + token, + keyList = this._key_list(); + + this.fire({ + type: "startkeyframerule", + keys: keyList, + line: keyList[0].line, + col: keyList[0].col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endkeyframerule", + keys: keyList, + line: keyList[0].line, + col: keyList[0].col + }); + + }, + + _key_list: function(){ + + /* + * key_list: + * : key [ S* ',' S* key]* + * ; + */ + var tokenStream = this._tokenStream, + token, + key, + keyList = []; + + //must be least one key + keyList.push(this._key()); + + this._readWhitespace(); + + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + keyList.push(this._key()); + this._readWhitespace(); + } + + return keyList; + }, + + _key: function(){ + /* + * There is a restriction that IDENT can be only "from" or "to". + * + * key + * : PERCENTAGE + * | IDENT + * ; + */ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.PERCENTAGE)){ + return SyntaxUnit.fromToken(tokenStream.token()); + } else if (tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + + if (/from|to/i.test(token.value)){ + return SyntaxUnit.fromToken(token); + } + + tokenStream.unget(); + } + + //if it gets here, there wasn't a valid token, so time to explode + this._unexpectedToken(tokenStream.LT(1)); + }, + + //----------------------------------------------------------------- + // Helper methods + //----------------------------------------------------------------- + + /** + * Not part of CSS grammar, but useful for skipping over + * combination of white space and HTML-style comments. + * @return {void} + * @method _skipCruft + * @private + */ + _skipCruft: function(){ + while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){ + //noop + } + }, + + /** + * Not part of CSS grammar, but this pattern occurs frequently + * in the official CSS grammar. Split out here to eliminate + * duplicate code. + * @param {Boolean} checkStart Indicates if the rule should check + * for the left brace at the beginning. + * @param {Boolean} readMargins Indicates if the rule should check + * for margin patterns. + * @return {void} + * @method _readDeclarations + * @private + */ + _readDeclarations: function(checkStart, readMargins){ + /* + * Reads the pattern + * S* '{' S* declaration [ ';' S* declaration ]* '}' S* + * or + * S* '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S* + * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect. + * A semicolon is only necessary following a delcaration is there's another declaration + * or margin afterwards. + */ + var tokenStream = this._tokenStream, + tt; + + + this._readWhitespace(); + + if (checkStart){ + tokenStream.mustMatch(Tokens.LBRACE); + } + + this._readWhitespace(); + + try { + + while(true){ + + if (readMargins && this._margin()){ + //noop + } else if (this._declaration()){ + if (!tokenStream.match(Tokens.SEMICOLON)){ + break; + } + } else { + break; + } + + //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){ + // break; + //} + this._readWhitespace(); + } + + tokenStream.mustMatch(Tokens.RBRACE); + this._readWhitespace(); + + } catch (ex) { + if (ex instanceof SyntaxError && !this.options.strict){ + + //fire error event + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + + //see if there's another declaration + tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); + if (tt == Tokens.SEMICOLON){ + //if there's a semicolon, then there might be another declaration + this._readDeclarations(false, readMargins); + } else if (tt == Tokens.RBRACE){ + //if there's a right brace, the rule is finished so don't do anything + } else { + //otherwise, rethrow the error because it wasn't handled properly + throw ex; + } + + } else { + //not a syntax error, rethrow it + throw ex; + } + } + + }, + + /** + * In some cases, you can end up with two white space tokens in a + * row. Instead of making a change in every function that looks for + * white space, this function is used to match as much white space + * as necessary. + * @method _readWhitespace + * @return {String} The white space if found, empty string if not. + * @private + */ + _readWhitespace: function(){ + + var tokenStream = this._tokenStream, + ws = ""; + + while(tokenStream.match(Tokens.S)){ + ws += tokenStream.token().value; + } + + return ws; + }, + + + /** + * Throws an error when an unexpected token is found. + * @param {Object} token The token that was found. + * @method _unexpectedToken + * @return {void} + * @private + */ + _unexpectedToken: function(token){ + throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + }, + + /** + * Helper method used for parsing subparts of a style sheet. + * @return {void} + * @method _verifyEnd + * @private + */ + _verifyEnd: function(){ + if (this._tokenStream.LA(1) != Tokens.EOF){ + this._unexpectedToken(this._tokenStream.LT(1)); + } + }, + + //----------------------------------------------------------------- + // Validation methods + //----------------------------------------------------------------- + _validateProperty: function(property, value){ + var name = property.text.toLowerCase(), + validation, + i, len; + + if (Properties[name]){ + + if (typeof Properties[name] == "function"){ + Properties[name](value); + } + + //otherwise, no validation available yet + } else if (name.indexOf("-") !== 0){ //vendor prefixed are ok + throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col); + } + }, + + //----------------------------------------------------------------- + // Parsing methods + //----------------------------------------------------------------- + + parse: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + this._stylesheet(); + }, + + parseStyleSheet: function(input){ + //just passthrough + return this.parse(input); + }, + + parseMediaQuery: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + var result = this._media_query(); + + //if there's anything more, then it's an invalid selector + this._verifyEnd(); + + //otherwise return result + return result; + }, + + /** + * Parses a property value (everything after the semicolon). + * @return {parserlib.css.PropertyValue} The property value. + * @throws parserlib.util.SyntaxError If an unexpected token is found. + * @method parserPropertyValue + */ + parsePropertyValue: function(input){ + + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._expr(); + + //okay to have a trailing white space + this._readWhitespace(); + + //if there's anything more, then it's an invalid selector + this._verifyEnd(); + + //otherwise return result + return result; + }, + + /** + * Parses a complete CSS rule, including selectors and + * properties. + * @param {String} input The text to parser. + * @return {Boolean} True if the parse completed successfully, false if not. + * @method parseRule + */ + parseRule: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + + //skip any leading white space + this._readWhitespace(); + + var result = this._ruleset(); + + //skip any trailing white space + this._readWhitespace(); + + //if there's anything more, then it's an invalid selector + this._verifyEnd(); + + //otherwise return result + return result; + }, + + /** + * Parses a single CSS selector (no comma) + * @param {String} input The text to parse as a CSS selector. + * @return {Selector} An object representing the selector. + * @throws parserlib.util.SyntaxError If an unexpected token is found. + * @method parseSelector + */ + parseSelector: function(input){ + + this._tokenStream = new TokenStream(input, Tokens); + + //skip any leading white space + this._readWhitespace(); + + var result = this._selector(); + + //skip any trailing white space + this._readWhitespace(); + + //if there's anything more, then it's an invalid selector + this._verifyEnd(); + + //otherwise return result + return result; + }, + + /** + * Parses an HTML style attribute: a set of CSS declarations + * separated by semicolons. + * @param {String} input The text to parse as a style attribute + * @return {void} + * @method parseStyleAttribute + */ + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); + } + }; + + //copy over onto prototype + for (prop in additions){ + proto[prop] = additions[prop]; + } + + return proto; +}(); + + +/* +nth + : S* [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? | + ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S* + ; +*/ +//This file will likely change a lot! Very experimental! + +var ValidationType = { + + "absolute-size": function(part){ + return this.identifier(part, "xx-small | x-small | small | medium | large | x-large | xx-large"); + }, + + "attachment": function(part){ + return this.identifier(part, "scroll | fixed | local"); + }, + + "box": function(part){ + return this.identifier(part, "padding-box | border-box | content-box"); + }, + + "relative-size": function(part){ + return this.identifier(part, "smaller | larger"); + }, + + "identifier": function(part, options){ + var text = part.text.toString().toLowerCase(), + args = options.split(" | "), + i, len, found = false; + + + for (i=0,len=args.length; i < len && !found; i++){ + if (text == args[i]){ + found = true; + } + } + + return found; + }, + + "length": function(part){ + return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0"; + }, + + "color": function(part){ + return part.type == "color" || part == "transparent"; + }, + + "number": function(part){ + return part.type == "number" || this.integer(part); + }, + + "integer": function(part){ + return part.type == "integer"; + }, + + "angle": function(part){ + return part.type == "angle"; + }, + + "uri": function(part){ + return part.type == "uri"; + }, + + "image": function(part){ + return this.uri(part); + }, + + "bg-image": function(part){ + return this.image(part) || part == "none"; + }, + + "percentage": function(part){ + return part.type == "percentage" || part == "0"; + }, + + "border-width": function(part){ + return this.length(part) || this.identifier(part, "thin | medium | thick"); + }, + + "border-style": function(part){ + return this.identifier(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"); + }, + + "margin-width": function(part){ + return this.length(part) || this.percentage(part) || this.identifier(part, "auto"); + }, + + "padding-width": function(part){ + return this.length(part) || this.percentage(part); + } +}; + + + + + + + +var Properties = { + + //A + "alignment-adjust": 1, + "alignment-baseline": 1, + "animation": 1, + "animation-delay": 1, + "animation-direction": { multi: [ "normal | alternate" ], separator: "," }, + "animation-duration": 1, + "animation-fill-mode": 1, + "animation-iteration-count": { multi: [ "number", "infinite"], separator: "," }, + "animation-name": 1, + "animation-play-state": { multi: [ "running | paused" ], separator: "," }, + "animation-timing-function": 1, + "appearance": 1, + "azimuth": 1, + + //B + "backface-visibility": 1, + "background": 1, + "background-attachment": { multi: [ "attachment" ], separator: "," }, + "background-break": 1, + "background-clip": { multi: [ "box" ], separator: "," }, + "background-color": [ "color", "inherit" ], + "background-image": { multi: [ "bg-image" ], separator: "," }, + "background-origin": { multi: [ "box" ], separator: "," }, + "background-position": 1, + "background-repeat": [ "repeat | repeat-x | repeat-y | no-repeat | inherit" ], + "background-size": 1, + "baseline-shift": 1, + "binding": 1, + "bleed": 1, + "bookmark-label": 1, + "bookmark-level": 1, + "bookmark-state": 1, + "bookmark-target": 1, + "border": 1, + "border-bottom": 1, + "border-bottom-color": 1, + "border-bottom-left-radius": 1, + "border-bottom-right-radius": 1, + "border-bottom-style": [ "border-style" ], + "border-bottom-width": [ "border-width" ], + "border-collapse": [ "collapse | separate | inherit" ], + "border-color": { multi: [ "color", "inherit" ], max: 4 }, + "border-image": 1, + "border-image-outset": { multi: [ "length", "number" ], max: 4 }, + "border-image-repeat": { multi: [ "stretch | repeat | round" ], max: 2 }, + "border-image-slice": 1, + "border-image-source": [ "image", "none" ], + "border-image-width": { multi: [ "length", "percentage", "number", "auto" ], max: 4 }, + "border-left": 1, + "border-left-color": [ "color", "inherit" ], + "border-left-style": [ "border-style" ], + "border-left-width": [ "border-width" ], + "border-radius": 1, + "border-right": 1, + "border-right-color": [ "color", "inherit" ], + "border-right-style": [ "border-style" ], + "border-right-width": [ "border-width" ], + "border-spacing": 1, + "border-style": { multi: [ "border-style" ], max: 4 }, + "border-top": 1, + "border-top-color": [ "color", "inherit" ], + "border-top-left-radius": 1, + "border-top-right-radius": 1, + "border-top-style": [ "border-style" ], + "border-top-width": [ "border-width" ], + "border-width": { multi: [ "border-width" ], max: 4 }, + "bottom": [ "margin-width", "inherit" ], + "box-align": [ "start | end | center | baseline | stretch" ], //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/ + "box-decoration-break": [ "slice |clone" ], + "box-direction": [ "normal | reverse | inherit" ], + "box-flex": [ "number" ], + "box-flex-group": [ "integer" ], + "box-lines": [ "single | multiple" ], + "box-ordinal-group": [ "integer" ], + "box-orient": [ "horizontal | vertical | inline-axis | block-axis | inherit" ], + "box-pack": [ "start | end | center | justify" ], + "box-shadow": 1, + "box-sizing": [ "content-box | border-box | inherit" ], + "break-after": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-before": [ "auto | always | avoid | left | right | page | column | avoid-page | avoid-column" ], + "break-inside": [ "auto | avoid | avoid-page | avoid-column" ], + + //C + "caption-side": [ "top | bottom | inherit" ], + "clear": [ "none | right | left | both | inherit" ], + "clip": 1, + "color": [ "color", "inherit" ], + "color-profile": 1, + "column-count": [ "integer", "auto" ], //http://www.w3.org/TR/css3-multicol/ + "column-fill": [ "auto | balance" ], + "column-gap": [ "length", "normal" ], + "column-rule": 1, + "column-rule-color": [ "color" ], + "column-rule-style": [ "border-style" ], + "column-rule-width": [ "border-width" ], + "column-span": [ "none | all" ], + "column-width": [ "length", "auto" ], + "columns": 1, + "content": 1, + "counter-increment": 1, + "counter-reset": 1, + "crop": 1, + "cue": [ "cue-after | cue-before | inherit" ], + "cue-after": 1, + "cue-before": 1, + "cursor": 1, + + //D + "direction": [ "ltr | rtl | inherit" ], + "display": [ "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid", "none | inherit" ], + "dominant-baseline": 1, + "drop-initial-after-adjust": 1, + "drop-initial-after-align": 1, + "drop-initial-before-adjust": 1, + "drop-initial-before-align": 1, + "drop-initial-size": 1, + "drop-initial-value": 1, + + //E + "elevation": 1, + "empty-cells": [ "show | hide | inherit" ], + + //F + "filter": 1, + "fit": [ "fill | hidden | meet | slice" ], + "fit-position": 1, + "float": [ "left | right | none | inherit" ], + "float-offset": 1, + "font": 1, + "font-family": 1, + "font-size": [ "absolute-size", "relative-size", "length", "percentage", "inherit" ], + "font-size-adjust": 1, + "font-stretch": 1, + "font-style": [ "normal | italic | oblique | inherit" ], + "font-variant": [ "normal | small-caps | inherit" ], + "font-weight": [ "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit" ], + + //G + "grid-cell-stacking": [ "columns | rows | layer" ], + "grid-column": 1, + "grid-columns": 1, + "grid-column-align": [ "start | end | center | stretch" ], + "grid-column-sizing": 1, + "grid-column-span": [ "integer" ], + "grid-flow": [ "none | rows | columns" ], + "grid-layer": [ "integer" ], + "grid-row": 1, + "grid-rows": 1, + "grid-row-align": [ "start | end | center | stretch" ], + "grid-row-span": [ "integer" ], + "grid-row-sizing": 1, + + //H + "hanging-punctuation": 1, + "height": [ "margin-width", "inherit" ], + "hyphenate-after": 1, + "hyphenate-before": 1, + "hyphenate-character": [ "string", "auto" ], + "hyphenate-lines": 1, + "hyphenate-resource": 1, + "hyphens": [ "none | manual | auto" ], + + //I + "icon": 1, + "image-orientation": [ "angle", "auto" ], + "image-rendering": 1, + "image-resolution": 1, + "inline-box-align": 1, + + //L + "left": [ "margin-width", "inherit" ], + "letter-spacing": [ "length", "normal | inherit" ], + "line-height": [ "number", "length", "percentage", "normal | inherit"], + "line-break": [ "auto | loose | normal | strict" ], + "line-stacking": 1, + "line-stacking-ruby": 1, + "line-stacking-shift": 1, + "line-stacking-strategy": 1, + "list-style": 1, + "list-style-image": [ "uri", "none | inherit" ], + "list-style-position": [ "inside | outside | inherit" ], + "list-style-type": [ "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit" ], + + //M + "margin": { multi: [ "margin-width", "inherit" ], max: 4 }, + "margin-bottom": [ "margin-width", "inherit" ], + "margin-left": [ "margin-width", "inherit" ], + "margin-right": [ "margin-width", "inherit" ], + "margin-top": [ "margin-width", "inherit" ], + "mark": 1, + "mark-after": 1, + "mark-before": 1, + "marks": 1, + "marquee-direction": 1, + "marquee-play-count": 1, + "marquee-speed": 1, + "marquee-style": 1, + "max-height": [ "length", "percentage", "none | inherit" ], + "max-width": [ "length", "percentage", "none | inherit" ], + "min-height": [ "length", "percentage", "inherit" ], + "min-width": [ "length", "percentage", "inherit" ], + "move-to": 1, + + //N + "nav-down": 1, + "nav-index": 1, + "nav-left": 1, + "nav-right": 1, + "nav-up": 1, + + //O + "opacity": [ "number", "inherit" ], + "orphans": [ "integer", "inherit" ], + "outline": 1, + "outline-color": [ "color", "invert | inherit" ], + "outline-offset": 1, + "outline-style": [ "border-style", "inherit" ], + "outline-width": [ "border-width", "inherit" ], + "overflow": [ "visible | hidden | scroll | auto | inherit" ], + "overflow-style": 1, + "overflow-x": 1, + "overflow-y": 1, + + //P + "padding": { multi: [ "padding-width", "inherit" ], max: 4 }, + "padding-bottom": [ "padding-width", "inherit" ], + "padding-left": [ "padding-width", "inherit" ], + "padding-right": [ "padding-width", "inherit" ], + "padding-top": [ "padding-width", "inherit" ], + "page": 1, + "page-break-after": [ "auto | always | avoid | left | right | inherit" ], + "page-break-before": [ "auto | always | avoid | left | right | inherit" ], + "page-break-inside": [ "auto | avoid | inherit" ], + "page-policy": 1, + "pause": 1, + "pause-after": 1, + "pause-before": 1, + "perspective": 1, + "perspective-origin": 1, + "phonemes": 1, + "pitch": 1, + "pitch-range": 1, + "play-during": 1, + "position": [ "static | relative | absolute | fixed | inherit" ], + "presentation-level": 1, + "punctuation-trim": 1, + + //Q + "quotes": 1, + + //R + "rendering-intent": 1, + "resize": 1, + "rest": 1, + "rest-after": 1, + "rest-before": 1, + "richness": 1, + "right": [ "margin-width", "inherit" ], + "rotation": 1, + "rotation-point": 1, + "ruby-align": 1, + "ruby-overhang": 1, + "ruby-position": 1, + "ruby-span": 1, + + //S + "size": 1, + "speak": [ "normal | none | spell-out | inherit" ], + "speak-header": [ "once | always | inherit" ], + "speak-numeral": [ "digits | continuous | inherit" ], + "speak-punctuation": [ "code | none | inherit" ], + "speech-rate": 1, + "src" : 1, + "stress": 1, + "string-set": 1, + + "table-layout": [ "auto | fixed | inherit" ], + "tab-size": [ "integer", "length" ], + "target": 1, + "target-name": 1, + "target-new": 1, + "target-position": 1, + "text-align": [ "left | right | center | justify | inherit" ], + "text-align-last": 1, + "text-decoration": 1, + "text-emphasis": 1, + "text-height": 1, + "text-indent": [ "length", "percentage", "inherit" ], + "text-justify": [ "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida" ], + "text-outline": 1, + "text-overflow": 1, + "text-shadow": 1, + "text-transform": [ "capitalize | uppercase | lowercase | none | inherit" ], + "text-wrap": [ "normal | none | avoid" ], + "top": [ "margin-width", "inherit" ], + "transform": 1, + "transform-origin": 1, + "transform-style": 1, + "transition": 1, + "transition-delay": 1, + "transition-duration": 1, + "transition-property": 1, + "transition-timing-function": 1, + + //U + "unicode-bidi": [ "normal | embed | bidi-override | inherit" ], + "user-modify": [ "read-only | read-write | write-only | inherit" ], + "user-select": [ "none | text | toggle | element | elements | all | inherit" ], + + //V + "vertical-align": [ "percentage", "length", "baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit" ], + "visibility": [ "visible | hidden | collapse | inherit" ], + "voice-balance": 1, + "voice-duration": 1, + "voice-family": 1, + "voice-pitch": 1, + "voice-pitch-range": 1, + "voice-rate": 1, + "voice-stress": 1, + "voice-volume": 1, + "volume": 1, + + //W + "white-space": [ "normal | pre | nowrap | pre-wrap | pre-line | inherit" ], + "white-space-collapse": 1, + "widows": [ "integer", "inherit" ], + "width": [ "length", "percentage", "auto", "inherit" ], + "word-break": [ "normal | keep-all | break-all" ], + "word-spacing": [ "length", "normal | inherit" ], + "word-wrap": 1, + + //Z + "z-index": [ "integer", "auto | inherit" ], + "zoom": [ "number", "percentage", "normal" ] +}; + +//Create validation functions for strings +(function(){ + var prop; + for (prop in Properties){ + if (Properties.hasOwnProperty(prop)){ + if (Properties[prop] instanceof Array){ + Properties[prop] = (function(values){ + return function(value){ + var valid = false, + msg = [], + part = value.parts[0]; + + if (value.parts.length != 1){ + throw new ValidationError("Expected 1 value but found " + value.parts.length + ".", value.line, value.col); + } + + for (var i=0, len=values.length; i < len && !valid; i++){ + if (typeof ValidationType[values[i]] == "undefined"){ + valid = valid || ValidationType.identifier(part, values[i]); + msg.push("one of (" + values[i] + ")"); + } else { + valid = valid || ValidationType[values[i]](part); + msg.push(values[i]); + } + } + + if (!valid){ + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + value + "'.", value.line, value.col); + } + }; + })(Properties[prop]); + } else if (typeof Properties[prop] == "object"){ + Properties[prop] = (function(spec){ + return function(value){ + var valid, + i, len, j, count, + msg, + values, + last, + parts = value.parts; + + //if there's a maximum set, use it (max can't be 0) + if (spec.max) { + if (parts.length > spec.max){ + throw new ValidationError("Expected a max of " + spec.max + " property values but found " + parts.length + ".", value.line, value.col); + } + } + + if (spec.multi){ + values = spec.multi; + } + + for (i=0, len=parts.length; i < len; i++){ + msg = []; + valid = false; + + if (spec.separator && parts[i].type == "operator"){ + + //two operators in a row - not allowed? + if ((last && last.type == "operator")){ + msg = msg.concat(values); + } else if (i == len-1){ + msg = msg.concat("end of line"); + } else if (parts[i] != spec.separator){ + msg.push("'" + spec.separator + "'"); + } else { + valid = true; + } + } else { + + for (j=0, count=values.length; j < count; j++){ + if (typeof ValidationType[values[j]] == "undefined"){ + if(ValidationType.identifier(parts[i], values[j])){ + valid = true; + break; + } + msg.push("one of (" + values[j] + ")"); + } else { + if (ValidationType[values[j]](parts[i])){ + valid = true; + break; + } + msg.push(values[j]); + } + } + } + + + if (!valid) { + throw new ValidationError("Expected " + msg.join(" or ") + " but found '" + parts[i] + "'.", value.line, value.col); + } + + + last = parts[i]; + } + + }; + })(Properties[prop]); + } + } + } +})(); +/** + * Represents a selector combinator (whitespace, +, >). + * @namespace parserlib.css + * @class PropertyName + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {String} text The text representation of the unit. + * @param {String} hack The type of IE hack applied ("*", "_", or null). + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function PropertyName(text, hack, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE); + + /** + * The type of IE hack applied ("*", "_", or null). + * @type String + * @property hack + */ + this.hack = hack; + +} + +PropertyName.prototype = new SyntaxUnit(); +PropertyName.prototype.constructor = PropertyName; +PropertyName.prototype.toString = function(){ + return (this.hack ? this.hack : "") + this.text; +}; +/** + * Represents a single part of a CSS property value, meaning that it represents + * just everything single part between ":" and ";". If there are multiple values + * separated by commas, this type represents just one of the values. + * @param {String[]} parts An array of value parts making up this value. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + * @namespace parserlib.css + * @class PropertyValue + * @extends parserlib.util.SyntaxUnit + * @constructor + */ +function PropertyValue(parts, line, col){ + + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE); + + /** + * The parts that make up the selector. + * @type Array + * @property parts + */ + this.parts = parts; + +} + +PropertyValue.prototype = new SyntaxUnit(); +PropertyValue.prototype.constructor = PropertyValue; + +/** + * Represents a single part of a CSS property value, meaning that it represents + * just one part of the data between ":" and ";". + * @param {String} text The text representation of the unit. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + * @namespace parserlib.css + * @class PropertyValuePart + * @extends parserlib.util.SyntaxUnit + * @constructor + */ +function PropertyValuePart(text, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE); + + /** + * Indicates the type of value unit. + * @type String + * @property type + */ + this.type = "unknown"; + + //figure out what type of data it is + + var temp; + + //it is a measurement? + if (/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)){ //dimension + this.type = "dimension"; + this.value = +RegExp.$1; + this.units = RegExp.$2; + + //try to narrow down + switch(this.units.toLowerCase()){ + + case "em": + case "rem": + case "ex": + case "px": + case "cm": + case "mm": + case "in": + case "pt": + case "pc": + this.type = "length"; + break; + + case "deg": + case "rad": + case "grad": + this.type = "angle"; + break; + + case "ms": + case "s": + this.type = "time"; + break; + + case "hz": + case "khz": + this.type = "frequency"; + break; + + case "dpi": + case "dpcm": + this.type = "resolution"; + break; + + //default + + } + + } else if (/^([+\-]?[\d\.]+)%$/i.test(text)){ //percentage + this.type = "percentage"; + this.value = +RegExp.$1; + } else if (/^([+\-]?[\d\.]+)%$/i.test(text)){ //percentage + this.type = "percentage"; + this.value = +RegExp.$1; + } else if (/^([+\-]?\d+)$/i.test(text)){ //integer + this.type = "integer"; + this.value = +RegExp.$1; + } else if (/^([+\-]?[\d\.]+)$/i.test(text)){ //number + this.type = "number"; + this.value = +RegExp.$1; + + } else if (/^#([a-f0-9]{3,6})/i.test(text)){ //hexcolor + this.type = "color"; + temp = RegExp.$1; + if (temp.length == 3){ + this.red = parseInt(temp.charAt(0)+temp.charAt(0),16); + this.green = parseInt(temp.charAt(1)+temp.charAt(1),16); + this.blue = parseInt(temp.charAt(2)+temp.charAt(2),16); + } else { + this.red = parseInt(temp.substring(0,2),16); + this.green = parseInt(temp.substring(2,4),16); + this.blue = parseInt(temp.substring(4,6),16); + } + } else if (/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)){ //rgb() color with absolute numbers + this.type = "color"; + this.red = +RegExp.$1; + this.green = +RegExp.$2; + this.blue = +RegExp.$3; + } else if (/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //rgb() color with percentages + this.type = "color"; + this.red = +RegExp.$1 * 255 / 100; + this.green = +RegExp.$2 * 255 / 100; + this.blue = +RegExp.$3 * 255 / 100; + } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers + this.type = "color"; + this.red = +RegExp.$1; + this.green = +RegExp.$2; + this.blue = +RegExp.$3; + this.alpha = +RegExp.$4; + } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages + this.type = "color"; + this.red = +RegExp.$1 * 255 / 100; + this.green = +RegExp.$2 * 255 / 100; + this.blue = +RegExp.$3 * 255 / 100; + this.alpha = +RegExp.$4; + } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl() + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages + this.type = "color"; + this.hue = +RegExp.$1; + this.saturation = +RegExp.$2 / 100; + this.lightness = +RegExp.$3 / 100; + this.alpha = +RegExp.$4; + } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI + this.type = "uri"; + this.uri = RegExp.$1; + } else if (/^["'][^"']*["']/.test(text)){ //string + this.type = "string"; + this.value = eval(text); + } else if (Colors[text.toLowerCase()]){ //named color + this.type = "color"; + temp = Colors[text.toLowerCase()].substring(1); + this.red = parseInt(temp.substring(0,2),16); + this.green = parseInt(temp.substring(2,4),16); + this.blue = parseInt(temp.substring(4,6),16); + } else if (/^[\,\/]$/.test(text)){ + this.type = "operator"; + this.value = text; + } else if (/^[a-z\-\u0080-\uFFFF][a-z0-9\-\u0080-\uFFFF]*$/i.test(text)){ + this.type = "identifier"; + this.value = text; + } + +} + +PropertyValuePart.prototype = new SyntaxUnit(); +PropertyValuePart.prototype.constructor = PropertyValue; + +/** + * Create a new syntax unit based solely on the given token. + * Convenience method for creating a new syntax unit when + * it represents a single token instead of multiple. + * @param {Object} token The token object to represent. + * @return {parserlib.css.PropertyValuePart} The object representing the token. + * @static + * @method fromToken + */ +PropertyValuePart.fromToken = function(token){ + return new PropertyValuePart(token.value, token.startLine, token.startCol); +}; +var Pseudos = { + ":first-letter": 1, + ":first-line": 1, + ":before": 1, + ":after": 1 +}; + +Pseudos.ELEMENT = 1; +Pseudos.CLASS = 2; + +Pseudos.isElement = function(pseudo){ + return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT; +}; +/** + * Represents an entire single selector, including all parts but not + * including multiple selectors (those separated by commas). + * @namespace parserlib.css + * @class Selector + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {Array} parts Array of selectors parts making up this selector. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function Selector(parts, line, col){ + + SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE); + + /** + * The parts that make up the selector. + * @type Array + * @property parts + */ + this.parts = parts; + + /** + * The specificity of the selector. + * @type parserlib.css.Specificity + * @property specificity + */ + this.specificity = Specificity.calculate(this); + +} + +Selector.prototype = new SyntaxUnit(); +Selector.prototype.constructor = Selector; + +/** + * Represents a single part of a selector string, meaning a single set of + * element name and modifiers. This does not include combinators such as + * spaces, +, >, etc. + * @namespace parserlib.css + * @class SelectorPart + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {String} elementName The element name in the selector or null + * if there is no element name. + * @param {Array} modifiers Array of individual modifiers for the element. + * May be empty if there are none. + * @param {String} text The text representation of the unit. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function SelectorPart(elementName, modifiers, text, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE); + + /** + * The tag name of the element to which this part + * of the selector affects. + * @type String + * @property elementName + */ + this.elementName = elementName; + + /** + * The parts that come after the element name, such as class names, IDs, + * pseudo classes/elements, etc. + * @type Array + * @property modifiers + */ + this.modifiers = modifiers; + +} + +SelectorPart.prototype = new SyntaxUnit(); +SelectorPart.prototype.constructor = SelectorPart; + +/** + * Represents a selector modifier string, meaning a class name, element name, + * element ID, pseudo rule, etc. + * @namespace parserlib.css + * @class SelectorSubPart + * @extends parserlib.util.SyntaxUnit + * @constructor + * @param {String} text The text representation of the unit. + * @param {String} type The type of selector modifier. + * @param {int} line The line of text on which the unit resides. + * @param {int} col The column of text on which the unit resides. + */ +function SelectorSubPart(text, type, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE); + + /** + * The type of modifier. + * @type String + * @property type + */ + this.type = type; + + /** + * Some subparts have arguments, this represents them. + * @type Array + * @property args + */ + this.args = []; + +} + +SelectorSubPart.prototype = new SyntaxUnit(); +SelectorSubPart.prototype.constructor = SelectorSubPart; + +/** + * Represents a selector's specificity. + * @namespace parserlib.css + * @class Specificity + * @constructor + * @param {int} a Should be 1 for inline styles, zero for stylesheet styles + * @param {int} b Number of ID selectors + * @param {int} c Number of classes and pseudo classes + * @param {int} d Number of element names and pseudo elements + */ +function Specificity(a, b, c, d){ + this.a = a; + this.b = b; + this.c = c; + this.d = d; +} + +Specificity.prototype = { + constructor: Specificity, + + /** + * Compare this specificity to another. + * @param {Specificity} other The other specificity to compare to. + * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal. + * @method compare + */ + compare: function(other){ + var comps = ["a", "b", "c", "d"], + i, len; + + for (i=0, len=comps.length; i < len; i++){ + if (this[comps[i]] < other[comps[i]]){ + return -1; + } else if (this[comps[i]] > other[comps[i]]){ + return 1; + } + } + + return 0; + }, + + /** + * Creates a numeric value for the specificity. + * @return {int} The numeric value for the specificity. + * @method valueOf + */ + valueOf: function(){ + return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d; + }, + + /** + * Returns a string representation for specificity. + * @return {String} The string representation of specificity. + * @method toString + */ + toString: function(){ + return this.a + "," + this.b + "," + this.c + "," + this.d; + } + +}; + +/** + * Calculates the specificity of the given selector. + * @param {parserlib.css.Selector} The selector to calculate specificity for. + * @return {parserlib.css.Specificity} The specificity of the selector. + * @static + * @method calculate + */ +Specificity.calculate = function(selector){ + + var i, len, + b=0, c=0, d=0; + + function updateValues(part){ + + var i, j, len, num, + modifier; + + if (part.elementName && part.text.charAt(part.text.length-1) != "*") { + d++; + } + + for (i=0, len=part.modifiers.length; i < len; i++){ + modifier = part.modifiers[i]; + switch(modifier.type){ + case "class": + case "attribute": + c++; + break; + + case "id": + b++; + break; + + case "pseudo": + if (Pseudos.isElement(modifier.text)){ + d++; + } else { + c++; + } + break; + + case "not": + for (j=0, num=modifier.args.length; j < num; j++){ + updateValues(modifier.args[j]); + } + } + } + } + + for (i=0, len=selector.parts.length; i < len; i++){ + part = selector.parts[i]; + + if (part instanceof SelectorPart){ + updateValues(part); + } + } + + return new Specificity(0, b, c, d); +}; + + +var h = /^[0-9a-fA-F]$/, + nonascii = /^[\u0080-\uFFFF]$/, + nl = /\n|\r\n|\r|\f/; + +//----------------------------------------------------------------------------- +// Helper functions +//----------------------------------------------------------------------------- + + +function isHexDigit(c){ + return c != null && h.test(c); +} + +function isDigit(c){ + return c != null && /\d/.test(c); +} + +function isWhitespace(c){ + return c != null && /\s/.test(c); +} + +function isNewLine(c){ + return c != null && nl.test(c); +} + +function isNameStart(c){ + return c != null && (/[a-z_\u0080-\uFFFF\\]/i.test(c)); +} + +function isNameChar(c){ + return c != null && (isNameStart(c) || /[0-9\-\\]/.test(c)); +} + +function isIdentStart(c){ + return c != null && (isNameStart(c) || /\-\\/.test(c)); +} + +function mix(receiver, supplier){ + for (var prop in supplier){ + if (supplier.hasOwnProperty(prop)){ + receiver[prop] = supplier[prop]; + } + } + return receiver; +} + +//----------------------------------------------------------------------------- +// CSS Token Stream +//----------------------------------------------------------------------------- + + +/** + * A token stream that produces CSS tokens. + * @param {String|Reader} input The source of text to tokenize. + * @constructor + * @class TokenStream + * @namespace parserlib.css + */ +function TokenStream(input){ + TokenStreamBase.call(this, input, Tokens); +} + +TokenStream.prototype = mix(new TokenStreamBase(), { + + /** + * Overrides the TokenStreamBase method of the same name + * to produce CSS tokens. + * @param {variant} channel The name of the channel to use + * for the next token. + * @return {Object} A token object representing the next token. + * @method _getToken + * @private + */ + _getToken: function(channel){ + + var c, + reader = this._reader, + token = null, + startLine = reader.getLine(), + startCol = reader.getCol(); + + c = reader.read(); + + + while(c){ + switch(c){ + + /* + * Potential tokens: + * - COMMENT + * - SLASH + * - CHAR + */ + case "/": + + if(reader.peek() == "*"){ + token = this.commentToken(c, startLine, startCol); + } else { + token = this.charToken(c, startLine, startCol); + } + break; + + /* + * Potential tokens: + * - DASHMATCH + * - INCLUDES + * - PREFIXMATCH + * - SUFFIXMATCH + * - SUBSTRINGMATCH + * - CHAR + */ + case "|": + case "~": + case "^": + case "$": + case "*": + if(reader.peek() == "="){ + token = this.comparisonToken(c, startLine, startCol); + } else { + token = this.charToken(c, startLine, startCol); + } + break; + + /* + * Potential tokens: + * - STRING + * - INVALID + */ + case "\"": + case "'": + token = this.stringToken(c, startLine, startCol); + break; + + /* + * Potential tokens: + * - HASH + * - CHAR + */ + case "#": + if (isNameChar(reader.peek())){ + token = this.hashToken(c, startLine, startCol); + } else { + token = this.charToken(c, startLine, startCol); + } + break; + + /* + * Potential tokens: + * - DOT + * - NUMBER + * - DIMENSION + * - PERCENTAGE + */ + case ".": + if (isDigit(reader.peek())){ + token = this.numberToken(c, startLine, startCol); + } else { + token = this.charToken(c, startLine, startCol); + } + break; + + /* + * Potential tokens: + * - CDC + * - MINUS + * - NUMBER + * - DIMENSION + * - PERCENTAGE + */ + case "-": + if (reader.peek() == "-"){ //could be closing HTML-style comment + token = this.htmlCommentEndToken(c, startLine, startCol); + } else if (isNameStart(reader.peek())){ + token = this.identOrFunctionToken(c, startLine, startCol); + } else { + token = this.charToken(c, startLine, startCol); + } + break; + + /* + * Potential tokens: + * - IMPORTANT_SYM + * - CHAR + */ + case "!": + token = this.importantToken(c, startLine, startCol); + break; + + /* + * Any at-keyword or CHAR + */ + case "@": + token = this.atRuleToken(c, startLine, startCol); + break; + + /* + * Potential tokens: + * - NOT + * - CHAR + */ + case ":": + token = this.notToken(c, startLine, startCol); + break; + + /* + * Potential tokens: + * - CDO + * - CHAR + */ + case "<": + token = this.htmlCommentStartToken(c, startLine, startCol); + break; + + /* + * Potential tokens: + * - UNICODE_RANGE + * - URL + * - CHAR + */ + case "U": + case "u": + if (reader.peek() == "+"){ + token = this.unicodeRangeToken(c, startLine, startCol); + break; + } + /*falls through*/ + + default: + + /* + * Potential tokens: + * - NUMBER + * - DIMENSION + * - LENGTH + * - FREQ + * - TIME + * - EMS + * - EXS + * - ANGLE + */ + if (isDigit(c)){ + token = this.numberToken(c, startLine, startCol); + } else + + /* + * Potential tokens: + * - S + */ + if (isWhitespace(c)){ + token = this.whitespaceToken(c, startLine, startCol); + } else + + /* + * Potential tokens: + * - IDENT + */ + if (isIdentStart(c)){ + token = this.identOrFunctionToken(c, startLine, startCol); + } else + + /* + * Potential tokens: + * - CHAR + * - PLUS + */ + { + token = this.charToken(c, startLine, startCol); + } + + + + + + + } + + //make sure this token is wanted + //TODO: check channel + break; + + c = reader.read(); + } + + if (!token && c == null){ + token = this.createToken(Tokens.EOF,null,startLine,startCol); + } + + return token; + }, + + //------------------------------------------------------------------------- + // Methods to create tokens + //------------------------------------------------------------------------- + + /** + * Produces a token based on available data and the current + * reader position information. This method is called by other + * private methods to create tokens and is never called directly. + * @param {int} tt The token type. + * @param {String} value The text value of the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @param {Object} options (Optional) Specifies a channel property + * to indicate that a different channel should be scanned + * and/or a hide property indicating that the token should + * be hidden. + * @return {Object} A token object. + * @method createToken + */ + createToken: function(tt, value, startLine, startCol, options){ + var reader = this._reader; + options = options || {}; + + return { + value: value, + type: tt, + channel: options.channel, + hide: options.hide || false, + startLine: startLine, + startCol: startCol, + endLine: reader.getLine(), + endCol: reader.getCol() + }; + }, + + //------------------------------------------------------------------------- + // Methods to create specific tokens + //------------------------------------------------------------------------- + + /** + * Produces a token for any at-rule. If the at-rule is unknown, then + * the token is for a single "@" character. + * @param {String} first The first character for the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method atRuleToken + */ + atRuleToken: function(first, startLine, startCol){ + var rule = first, + reader = this._reader, + tt = Tokens.CHAR, + valid = false, + ident, + c; + + /* + * First, mark where we are. There are only four @ rules, + * so anything else is really just an invalid token. + * Basically, if this doesn't match one of the known @ + * rules, just return '@' as an unknown token and allow + * parsing to continue after that point. + */ + reader.mark(); + + //try to find the at-keyword + ident = this.readName(); + rule = first + ident; + tt = Tokens.type(rule.toLowerCase()); + + //if it's not valid, use the first character only and reset the reader + if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){ + tt = Tokens.CHAR; + rule = first; + reader.reset(); + } + + return this.createToken(tt, rule, startLine, startCol); + }, + + /** + * Produces a character token based on the given character + * and location in the stream. If there's a special (non-standard) + * token name, this is used; otherwise CHAR is used. + * @param {String} c The character for the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method charToken + */ + charToken: function(c, startLine, startCol){ + var tt = Tokens.type(c); + + if (tt == -1){ + tt = Tokens.CHAR; + } + + return this.createToken(tt, c, startLine, startCol); + }, + + /** + * Produces a character token based on the given character + * and location in the stream. If there's a special (non-standard) + * token name, this is used; otherwise CHAR is used. + * @param {String} first The first character for the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method commentToken + */ + commentToken: function(first, startLine, startCol){ + var reader = this._reader, + comment = this.readComment(first); + + return this.createToken(Tokens.COMMENT, comment, startLine, startCol); + }, + + /** + * Produces a comparison token based on the given character + * and location in the stream. The next character must be + * read and is already known to be an equals sign. + * @param {String} c The character for the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method comparisonToken + */ + comparisonToken: function(c, startLine, startCol){ + var reader = this._reader, + comparison = c + reader.read(), + tt = Tokens.type(comparison) || Tokens.CHAR; + + return this.createToken(tt, comparison, startLine, startCol); + }, + + /** + * Produces a hash token based on the specified information. The + * first character provided is the pound sign (#) and then this + * method reads a name afterward. + * @param {String} first The first character (#) in the hash name. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method hashToken + */ + hashToken: function(first, startLine, startCol){ + var reader = this._reader, + name = this.readName(first); + + return this.createToken(Tokens.HASH, name, startLine, startCol); + }, + + /** + * Produces a CDO or CHAR token based on the specified information. The + * first character is provided and the rest is read by the function to determine + * the correct token to create. + * @param {String} first The first character in the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method htmlCommentStartToken + */ + htmlCommentStartToken: function(first, startLine, startCol){ + var reader = this._reader, + text = first; + + reader.mark(); + text += reader.readCount(3); + + if (text == ""){ + return this.createToken(Tokens.CDC, text, startLine, startCol); + } else { + reader.reset(); + return this.charToken(first, startLine, startCol); + } + }, + + /** + * Produces an IDENT or FUNCTION token based on the specified information. The + * first character is provided and the rest is read by the function to determine + * the correct token to create. + * @param {String} first The first character in the identifier. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method identOrFunctionToken + */ + identOrFunctionToken: function(first, startLine, startCol){ + var reader = this._reader, + ident = this.readName(first), + tt = Tokens.IDENT; + + //if there's a left paren immediately after, it's a URI or function + if (reader.peek() == "("){ + ident += reader.read(); + if (ident.toLowerCase() == "url("){ + tt = Tokens.URI; + ident = this.readURI(ident); + + //didn't find a valid URL or there's no closing paren + if (ident.toLowerCase() == "url("){ + tt = Tokens.FUNCTION; + } + } else { + tt = Tokens.FUNCTION; + } + } else if (reader.peek() == ":"){ //might be an IE function + + //IE-specific functions always being with progid: + if (ident.toLowerCase() == "progid"){ + ident += reader.readTo("("); + tt = Tokens.IE_FUNCTION; + } + } + + return this.createToken(tt, ident, startLine, startCol); + }, + + /** + * Produces an IMPORTANT_SYM or CHAR token based on the specified information. The + * first character is provided and the rest is read by the function to determine + * the correct token to create. + * @param {String} first The first character in the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method importantToken + */ + importantToken: function(first, startLine, startCol){ + var reader = this._reader, + important = first, + tt = Tokens.CHAR, + temp, + c; + + reader.mark(); + c = reader.read(); + + while(c){ + + //there can be a comment in here + if (c == "/"){ + + //if the next character isn't a star, then this isn't a valid !important token + if (reader.peek() != "*"){ + break; + } else { + temp = this.readComment(c); + if (temp == ""){ //broken! + break; + } + } + } else if (isWhitespace(c)){ + important += c + this.readWhitespace(); + } else if (/i/i.test(c)){ + temp = reader.readCount(8); + if (/mportant/i.test(temp)){ + important += c + temp; + tt = Tokens.IMPORTANT_SYM; + + } + break; //we're done + } else { + break; + } + + c = reader.read(); + } + + if (tt == Tokens.CHAR){ + reader.reset(); + return this.charToken(first, startLine, startCol); + } else { + return this.createToken(tt, important, startLine, startCol); + } + + + }, + + /** + * Produces a NOT or CHAR token based on the specified information. The + * first character is provided and the rest is read by the function to determine + * the correct token to create. + * @param {String} first The first character in the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method notToken + */ + notToken: function(first, startLine, startCol){ + var reader = this._reader, + text = first; + + reader.mark(); + text += reader.readCount(4); + + if (text.toLowerCase() == ":not("){ + return this.createToken(Tokens.NOT, text, startLine, startCol); + } else { + reader.reset(); + return this.charToken(first, startLine, startCol); + } + }, + + /** + * Produces a number token based on the given character + * and location in the stream. This may return a token of + * NUMBER, EMS, EXS, LENGTH, ANGLE, TIME, FREQ, DIMENSION, + * or PERCENTAGE. + * @param {String} first The first character for the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method numberToken + */ + numberToken: function(first, startLine, startCol){ + var reader = this._reader, + value = this.readNumber(first), + ident, + tt = Tokens.NUMBER, + c = reader.peek(); + + if (isIdentStart(c)){ + ident = this.readName(reader.read()); + value += ident; + + if (/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vm$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(ident)){ + tt = Tokens.LENGTH; + } else if (/^deg|^rad$|^grad$/i.test(ident)){ + tt = Tokens.ANGLE; + } else if (/^ms$|^s$/i.test(ident)){ + tt = Tokens.TIME; + } else if (/^hz$|^khz$/i.test(ident)){ + tt = Tokens.FREQ; + } else if (/^dpi$|^dpcm$/i.test(ident)){ + tt = Tokens.RESOLUTION; + } else { + tt = Tokens.DIMENSION; + } + + } else if (c == "%"){ + value += reader.read(); + tt = Tokens.PERCENTAGE; + } + + return this.createToken(tt, value, startLine, startCol); + }, + + /** + * Produces a string token based on the given character + * and location in the stream. Since strings may be indicated + * by single or double quotes, a failure to match starting + * and ending quotes results in an INVALID token being generated. + * The first character in the string is passed in and then + * the rest are read up to and including the final quotation mark. + * @param {String} first The first character in the string. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method stringToken + */ + stringToken: function(first, startLine, startCol){ + var delim = first, + string = first, + reader = this._reader, + prev = first, + tt = Tokens.STRING, + c = reader.read(); + + while(c){ + string += c; + + //if the delimiter is found with an escapement, we're done. + if (c == delim && prev != "\\"){ + break; + } + + //if there's a newline without an escapement, it's an invalid string + if (isNewLine(reader.peek()) && c != "\\"){ + tt = Tokens.INVALID; + break; + } + + //save previous and get next + prev = c; + c = reader.read(); + } + + //if c is null, that means we're out of input and the string was never closed + if (c == null){ + tt = Tokens.INVALID; + } + + return this.createToken(tt, string, startLine, startCol); + }, + + unicodeRangeToken: function(first, startLine, startCol){ + var reader = this._reader, + value = first, + temp, + tt = Tokens.CHAR; + + //then it should be a unicode range + if (reader.peek() == "+"){ + reader.mark(); + value += reader.read(); + value += this.readUnicodeRangePart(true); + + //ensure there's an actual unicode range here + if (value.length == 2){ + reader.reset(); + } else { + + tt = Tokens.UNICODE_RANGE; + + //if there's a ? in the first part, there can't be a second part + if (value.indexOf("?") == -1){ + + if (reader.peek() == "-"){ + reader.mark(); + temp = reader.read(); + temp += this.readUnicodeRangePart(false); + + //if there's not another value, back up and just take the first + if (temp.length == 1){ + reader.reset(); + } else { + value += temp; + } + } + + } + } + } + + return this.createToken(tt, value, startLine, startCol); + }, + + /** + * Produces a S token based on the specified information. Since whitespace + * may have multiple characters, this consumes all whitespace characters + * into a single token. + * @param {String} first The first character in the token. + * @param {int} startLine The beginning line for the character. + * @param {int} startCol The beginning column for the character. + * @return {Object} A token object. + * @method whitespaceToken + */ + whitespaceToken: function(first, startLine, startCol){ + var reader = this._reader, + value = first + this.readWhitespace(); + return this.createToken(Tokens.S, value, startLine, startCol); + }, + + + + + //------------------------------------------------------------------------- + // Methods to read values from the string stream + //------------------------------------------------------------------------- + + readUnicodeRangePart: function(allowQuestionMark){ + var reader = this._reader, + part = "", + c = reader.peek(); + + //first read hex digits + while(isHexDigit(c) && part.length < 6){ + reader.read(); + part += c; + c = reader.peek(); + } + + //then read question marks if allowed + if (allowQuestionMark){ + while(c == "?" && part.length < 6){ + reader.read(); + part += c; + c = reader.peek(); + } + } + + //there can't be any other characters after this point + + return part; + }, + + readWhitespace: function(){ + var reader = this._reader, + whitespace = "", + c = reader.peek(); + + while(isWhitespace(c)){ + reader.read(); + whitespace += c; + c = reader.peek(); + } + + return whitespace; + }, + readNumber: function(first){ + var reader = this._reader, + number = first, + hasDot = (first == "."), + c = reader.peek(); + + + while(c){ + if (isDigit(c)){ + number += reader.read(); + } else if (c == "."){ + if (hasDot){ + break; + } else { + hasDot = true; + number += reader.read(); + } + } else { + break; + } + + c = reader.peek(); + } + + return number; + }, + readString: function(){ + var reader = this._reader, + delim = reader.read(), + string = delim, + prev = delim, + c = reader.peek(); + + while(c){ + c = reader.read(); + string += c; + + //if the delimiter is found with an escapement, we're done. + if (c == delim && prev != "\\"){ + break; + } + + //if there's a newline without an escapement, it's an invalid string + if (isNewLine(reader.peek()) && c != "\\"){ + string = ""; + break; + } + + //save previous and get next + prev = c; + c = reader.peek(); + } + + //if c is null, that means we're out of input and the string was never closed + if (c == null){ + string = ""; + } + + return string; + }, + readURI: function(first){ + var reader = this._reader, + uri = first, + inner = "", + c = reader.peek(); + + reader.mark(); + + //skip whitespace before + while(c && isWhitespace(c)){ + reader.read(); + c = reader.peek(); + } + + //it's a string + if (c == "'" || c == "\""){ + inner = this.readString(); + } else { + inner = this.readURL(); + } + + c = reader.peek(); + + //skip whitespace after + while(c && isWhitespace(c)){ + reader.read(); + c = reader.peek(); + } + + //if there was no inner value or the next character isn't closing paren, it's not a URI + if (inner == "" || c != ")"){ + uri = first; + reader.reset(); + } else { + uri += inner + reader.read(); + } + + return uri; + }, + readURL: function(){ + var reader = this._reader, + url = "", + c = reader.peek(); + + //TODO: Check for escape and nonascii + while (/^[!#$%&\\*-~]$/.test(c)){ + url += reader.read(); + c = reader.peek(); + } + + return url; + + }, + readName: function(first){ + var reader = this._reader, + ident = first || "", + c = reader.peek(); + + while(true){ + if (c == "\\"){ + ident += this.readEscape(reader.read()); + c = reader.peek(); + } else if(c && isNameChar(c)){ + ident += reader.read(); + c = reader.peek(); + } else { + break; + } + } + + return ident; + }, + + readEscape: function(first){ + var reader = this._reader, + cssEscape = first || "", + i = 0, + c = reader.peek(); + + if (isHexDigit(c)){ + do { + cssEscape += reader.read(); + c = reader.peek(); + } while(c && isHexDigit(c) && ++i < 6); + } + + if (cssEscape.length == 3 && /\s/.test(c) || + cssEscape.length == 7 || cssEscape.length == 1){ + reader.read(); + } else { + c = ""; + } + + return cssEscape + c; + }, + + readComment: function(first){ + var reader = this._reader, + comment = first || "", + c = reader.read(); + + if (c == "*"){ + while(c){ + comment += c; + + //look for end of comment + if (comment.length > 2 && c == "*" && reader.peek() == "/"){ + comment += reader.read(); + break; + } + + c = reader.read(); + } + + return comment; + } else { + return ""; + } + + } +}); + +var Tokens = [ + + /* + * The following token names are defined in CSS3 Grammar: http://www.w3.org/TR/css3-syntax/#lexical + */ + + //HTML-style comments + { name: "CDO"}, + { name: "CDC"}, + + //ignorables + { name: "S", whitespace: true/*, channel: "ws"*/}, + { name: "COMMENT", comment: true, hide: true, channel: "comment" }, + + //attribute equality + { name: "INCLUDES", text: "~="}, + { name: "DASHMATCH", text: "|="}, + { name: "PREFIXMATCH", text: "^="}, + { name: "SUFFIXMATCH", text: "$="}, + { name: "SUBSTRINGMATCH", text: "*="}, + + //identifier types + { name: "STRING"}, + { name: "IDENT"}, + { name: "HASH"}, + + //at-keywords + { name: "IMPORT_SYM", text: "@import"}, + { name: "PAGE_SYM", text: "@page"}, + { name: "MEDIA_SYM", text: "@media"}, + { name: "FONT_FACE_SYM", text: "@font-face"}, + { name: "CHARSET_SYM", text: "@charset"}, + { name: "NAMESPACE_SYM", text: "@namespace"}, + //{ name: "ATKEYWORD"}, + + //CSS3 animations + { name: "KEYFRAMES_SYM", text: [ "@keyframes", "@-webkit-keyframes", "@-moz-keyframes" ] }, + + //important symbol + { name: "IMPORTANT_SYM"}, + + //measurements + { name: "LENGTH"}, + { name: "ANGLE"}, + { name: "TIME"}, + { name: "FREQ"}, + { name: "DIMENSION"}, + { name: "PERCENTAGE"}, + { name: "NUMBER"}, + + //functions + { name: "URI"}, + { name: "FUNCTION"}, + + //Unicode ranges + { name: "UNICODE_RANGE"}, + + /* + * The following token names are defined in CSS3 Selectors: http://www.w3.org/TR/css3-selectors/#selector-syntax + */ + + //invalid string + { name: "INVALID"}, + + //combinators + { name: "PLUS", text: "+" }, + { name: "GREATER", text: ">"}, + { name: "COMMA", text: ","}, + { name: "TILDE", text: "~"}, + + //modifier + { name: "NOT"}, + + /* + * Defined in CSS3 Paged Media + */ + { name: "TOPLEFTCORNER_SYM", text: "@top-left-corner"}, + { name: "TOPLEFT_SYM", text: "@top-left"}, + { name: "TOPCENTER_SYM", text: "@top-center"}, + { name: "TOPRIGHT_SYM", text: "@top-right"}, + { name: "TOPRIGHTCORNER_SYM", text: "@top-right-corner"}, + { name: "BOTTOMLEFTCORNER_SYM", text: "@bottom-left-corner"}, + { name: "BOTTOMLEFT_SYM", text: "@bottom-left"}, + { name: "BOTTOMCENTER_SYM", text: "@bottom-center"}, + { name: "BOTTOMRIGHT_SYM", text: "@bottom-right"}, + { name: "BOTTOMRIGHTCORNER_SYM", text: "@bottom-right-corner"}, + { name: "LEFTTOP_SYM", text: "@left-top"}, + { name: "LEFTMIDDLE_SYM", text: "@left-middle"}, + { name: "LEFTBOTTOM_SYM", text: "@left-bottom"}, + { name: "RIGHTTOP_SYM", text: "@right-top"}, + { name: "RIGHTMIDDLE_SYM", text: "@right-middle"}, + { name: "RIGHTBOTTOM_SYM", text: "@right-bottom"}, + + /* + * The following token names are defined in CSS3 Media Queries: http://www.w3.org/TR/css3-mediaqueries/#syntax + */ + /*{ name: "MEDIA_ONLY", state: "media"}, + { name: "MEDIA_NOT", state: "media"}, + { name: "MEDIA_AND", state: "media"},*/ + { name: "RESOLUTION", state: "media"}, + + /* + * The following token names are not defined in any CSS specification but are used by the lexer. + */ + + //not a real token, but useful for stupid IE filters + { name: "IE_FUNCTION" }, + + //part of CSS3 grammar but not the Flex code + { name: "CHAR" }, + + //TODO: Needed? + //Not defined as tokens, but might as well be + { + name: "PIPE", + text: "|" + }, + { + name: "SLASH", + text: "/" + }, + { + name: "MINUS", + text: "-" + }, + { + name: "STAR", + text: "*" + }, + + { + name: "LBRACE", + text: "{" + }, + { + name: "RBRACE", + text: "}" + }, + { + name: "LBRACKET", + text: "[" + }, + { + name: "RBRACKET", + text: "]" + }, + { + name: "EQUALS", + text: "=" + }, + { + name: "COLON", + text: ":" + }, + { + name: "SEMICOLON", + text: ";" + }, + + { + name: "LPAREN", + text: "(" + }, + { + name: "RPAREN", + text: ")" + }, + { + name: "DOT", + text: "." + } +]; + +(function(){ + + var nameMap = [], + typeMap = {}; + + Tokens.UNKNOWN = -1; + Tokens.unshift({name:"EOF"}); + for (var i=0, len = Tokens.length; i < len; i++){ + nameMap.push(Tokens[i].name); + Tokens[Tokens[i].name] = i; + if (Tokens[i].text){ + if (Tokens[i].text instanceof Array){ + for (var j=0; j < Tokens[i].text.length; j++){ + typeMap[Tokens[i].text[j]] = i; + } + } else { + typeMap[Tokens[i].text] = i; + } + } + } + + Tokens.name = function(tt){ + return nameMap[tt]; + }; + + Tokens.type = function(c){ + return typeMap[c] || -1; + }; + +})(); + + + +/** + * Type to use when a validation error occurs. + * @class ValidationError + * @namespace parserlib.util + * @constructor + * @param {String} message The error message. + * @param {int} line The line at which the error occurred. + * @param {int} col The column at which the error occurred. + */ +function ValidationError(message, line, col){ + + /** + * The column at which the error occurred. + * @type int + * @property col + */ + this.col = col; + + /** + * The line at which the error occurred. + * @type int + * @property line + */ + this.line = line; + + /** + * The text representation of the unit. + * @type String + * @property text + */ + this.message = message; + +} + +//inherit from Error +ValidationError.prototype = new Error(); + +parserlib.css = { +Colors :Colors, +Combinator :Combinator, +Parser :Parser, +PropertyName :PropertyName, +PropertyValue :PropertyValue, +PropertyValuePart :PropertyValuePart, +MediaFeature :MediaFeature, +MediaQuery :MediaQuery, +Selector :Selector, +SelectorPart :SelectorPart, +SelectorSubPart :SelectorSubPart, +Specificity :Specificity, +TokenStream :TokenStream, +Tokens :Tokens, +ValidationError :ValidationError +}; +})(); + + + +/************************************************************************ + * src/impl/URL.js + ************************************************************************/ + +//@line 1 "src/impl/URL.js" +function URL(url) { + if (!url) return Object.create(URL.prototype); + // Can't use String.trim() since it defines whitespace differently than HTML + this.url = url.replace(/^[ \t\n\r\f]+|[ \t\n\r\f]+$/g, ""); + + // See http://tools.ietf.org/html/rfc3986#appendix-B + var match = URL.pattern.exec(this.url); + if (match) { + if (match[2]) this.scheme = match[2]; + if (match[4]) { + // XXX ignoring userinfo before the hostname + if (match[4].match(URL.portPattern)) { + var pos = S.lastIndexOf(match[4], ":"); + this.host = substring(match[4], 0, pos); + this.port = substring(match[4], pos+1); + } + else { + this.host = match[4]; + } + } + if (match[5]) this.path = match[5]; + if (match[6]) this.query = match[7]; + if (match[8]) this.fragment = match[9]; + } +} + +URL.pattern = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/; +URL.portPattern = /:\d+$/ +URL.authorityPattern = /^[^:\/?#]+:\/\//; +URL.hierarchyPattern = /^[^:\/?#]+:\//; + +// Return a percentEncoded version of s. +// S should be a single-character string +// XXX: needs to do utf-8 encoding? +URL.percentEncode = function percentEncode(s) { + var c = charCodeAt(s, 0); + if (c < 256) return "%" + c.toString(16); + else throw Error("can't percent-encode codepoints > 255 yet"); +}; + +URL.prototype = { + constructor: URL, + + // XXX: not sure if this is the precise definition of absolute + isAbsolute: function() { return !!this.scheme; }, + isAuthorityBased: function() { + return URL.authorityPattern.test(this.url); + }, + isHierarchical: function() { + return URL.hierarchyPattern.test(this.url); + }, + + toString: function() { + var s = ""; + if (this.scheme !== undefined) s += this.scheme + ":"; + if (this.host !== undefined) s += "//" + this.host; + if (this.port !== undefined) s += ":" + this.port; + if (this.path !== undefined) s += this.path; + if (this.query !== undefined) s += "?" + this.query; + if (this.fragment !== undefined) s += "#" + this.fragment; + return s; + }, + + // See: http://tools.ietf.org/html/rfc3986#section-5.2 + resolve: function(relative) { + var base = this; // The base url we're resolving against + var r = new URL(relative); // The relative reference url to resolve + var t = new URL(); // The absolute target url we will return + + if (r.scheme !== undefined) { + t.scheme = r.scheme; + t.host = r.host; + t.port = r.port; + t.path = remove_dot_segments(r.path); + t.query = r.query; + } + else { + t.scheme = base.scheme; + if (r.host !== undefined) { + t.host = r.host; + t.port = r.port; + t.path = remove_dot_segments(r.path); + t.query = r.query; + } + else { + t.host = base.host; + t.port = base.port; + if (!r.path) { // undefined or empty + t.path = base.path; + if (r.query !== undefined) + t.query = r.query; + else + t.query = base.query; + } + else { + if (r.path.charAt(0) === "/") { + t.path = remove_dot_segments(r.path); + } + else { + t.path = merge(base.path, r.path); + t.path = remove_dot_segments(t.path); + } + t.query = r.query; + } + } + } + t.fragment = r.fragment; + + return t.toString(); + + + function merge(basepath, refpath) { + if (base.host !== undefined && !base.path) + return "/" + refpath; + + var lastslash = basepath.lastIndexOf("/"); + if (lastslash === -1) + return refpath; + else + return basepath.substring(0, lastslash+1) + refpath; + } + + function remove_dot_segments(path) { + if (!path) return path; // For "" or undefined + + var output = ""; + while(path.length > 0) { + if (path === "." || path === "..") { + path = ""; + break; + } + + var twochars = path.substring(0,2); + var threechars = path.substring(0,3); + var fourchars = path.substring(0,4); + if (threechars === "../") { + path = path.substring(3); + } + else if (twochars === "./") { + path = path.substring(2); + } + else if (threechars === "/./") { + path = "/" + path.substring(3); + } + else if (twochars === "/." && path.length === 2) { + path = "/"; + } + else if (fourchars === "/../" || + (threechars === "/.." && path.length === 3)) { + path = "/" + path.substring(4); + + output = output.replace(/\/?[^\/]*$/, ""); + } + else { + var segment = path.match(/(\/?([^\/]*))/)[0]; + output += segment; + path = path.substring(segment.length); + } + } + + + return output; + } + }, +}; + + + +/************************************************************************ + * src/impl/URLDecompositionAttributes.js + ************************************************************************/ + +//@line 1 "src/impl/URLDecompositionAttributes.js" +// This is an abstract superclass for Location, HTMLAnchorElement and +// other types that have the standard complement of "URL decomposition +// IDL attributes". +// Subclasses must define getInput() and setOutput() methods. +// The getter and setter methods parse and rebuild the URL on each +// invocation; there is no attempt to cache the value and be more efficient +function URLDecompositionAttributes() {} +URLDecompositionAttributes.prototype = { + constructor: URLDecompositionAttributes, + + get protocol() { + var url = new URL(this.getInput()); + if (url.isAbsolute()) return url.scheme + ":"; + else return ""; + }, + + get host() { + var url = new URL(this.getInput()); + if (url.isAbsolute() && url.isAuthorityBased()) + return url.host + (url.port ? (":" + url.port) : ""); + else + return ""; + }, + + get hostname() { + var url = new URL(this.getInput()); + if (url.isAbsolute() && url.isAuthorityBased()) + return url.host; + else + return ""; + }, + + get port() { + var url = new URL(this.getInput()); + if (url.isAbsolute() && url.isAuthorityBased() && url.port!==undefined) + return url.port; + else + return ""; + }, + + get pathname() { + var url = new URL(this.getInput()); + if (url.isAbsolute() && url.isHierarchical()) + return url.path; + else + return ""; + }, + + get search() { + var url = new URL(this.getInput()); + if (url.isAbsolute() && url.isHierarchical() && url.query!==undefined) + return "?" + url.query; + else + return ""; + }, + + get hash() { + var url = new URL(this.getInput()); + if (url.isAbsolute() && url.fragment != undefined) + return "#" + url.fragment; + else + return ""; + }, + + + set protocol(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute()) { + v = v.replace(/:+$/, ""); + v = v.replace(/[^-+\.a-zA-z0-9]/g, URL.percentEncode); + if (v.length > 0) { + url.scheme = v; + output = url.toString(); + } + } + this.setOutput(output); + }, + + set host(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute() && url.isAuthorityBased()) { + v = v.replace(/[^-+\._~!$&'()*,;:=a-zA-z0-9]/g, URL.percentEncode); + if (v.length > 0) { + url.host = v; + delete url.port; + output = url.toString(); + } + } + this.setOutput(output); + }, + + set hostname(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute() && url.isAuthorityBased()) { + v = v.replace(/^\/+/, ""); + v = v.replace(/[^-+\._~!$&'()*,;:=a-zA-z0-9]/g, URL.percentEncode); + if (v.length > 0) { + url.host = v; + output = url.toString(); + } + } + this.setOutput(output); + }, + + set port(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute() && url.isAuthorityBased()) { + v = v.replace(/[^0-9].*$/, ""); + v = v.replace(/^0+/, ""); + if (v.length === 0) v = "0"; + if (parseInt(v, 10) <= 65535) { + url.port = v; + output = url.toString(); + } + } + this.setOutput(output); + }, + + set pathname(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute() && url.isHierarchical()) { + if (v.charAt(0) !== "/") + v = "/" + v; + v = v.replace(/[^-+\._~!$&'()*,;:=@\/a-zA-z0-9]/g, + URL.percentEncode); + url.path = v; + output = url.toString(); + } + this.setOutput(output); + }, + + set search(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute() && url.isHierarchical()) { + if (v.charAt(0) !== "?") v = v.substring(1); + v = v.replace(/[^-+\._~!$&'()*,;:=@\/?a-zA-z0-9]/g, + URL.percentEncode); + url.query = v; + output = url.toString(); + } + this.setOutput(output); + }, + + set hash(v) { + var output = this.getInput(); + var url = new URL(output); + if (url.isAbsolute()) { + if (v.charAt(0) !== "#") v = v.substring(1); + v = v.replace(/[^-+\._~!$&'()*,;:=@\/?a-zA-z0-9]/g, + URL.percentEncode); + url.fragment = v; + output = url.toString(); + } + this.setOutput(output); + } +} + + + +/************************************************************************ + * src/impl/Location.js + ************************************************************************/ + +//@line 1 "src/impl/Location.js" +function Location(window, href) { + this._window = window; + this._href = href; +} + +Location.prototype = Object.create(URLDecompositionAttributes.prototype, { + _idlName: constant("Location"), + constructor: constant(Location), + // The concrete methods that the superclass needs + getInput: constant(function() { return this.href; }), + setOutput: constant(function(v) { this.href = v; }), + + // Special behavior when href is set + href: attribute( + function() { return this._href; }, + function(v) { this.assign(v) } + ), + + assign: constant(function(url) { + // Resolve the new url against the current one + // XXX: + // This is not actually correct. It should be resolved against + // the URL of the document of the script. For now, though, I only + // support a single window and there is only one base url. + // So this is good enough for now. + var current = new URL(this._href); + var newurl = current.resolve(url); + var self = this; // for the XHR callback below + + // Save the new url + this._href = newurl; + + // Start loading the new document! + // XXX + // This is just something hacked together. + // The real algorithm is: http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#navigate + var xhr = new XMLHttpRequest(); + + xhr.onload = function() { + var olddoc = self._window.document; + var parser = new HTMLParser(newurl); + var newdoc = unwrap(parser.document()); + newdoc.mutationHandler = olddoc.mutationHandler; + + // Get rid of any current content in the old doc + // XXX + // Should we have a special mutation event that means + // discard the entire document because we're loading a new one? + while(olddoc.hasChildNodes()) olddoc.removeChild(olddoc.firstChild); + + // Make the new document the current document in the window + self._window.document = newdoc; + newdoc.defaultView = self._window; + + // And parse the new file + parser.parse(xhr.responseText, true); + }; + + xhr.open("GET", newurl); + xhr.send(); + + }), + + replace: constant(function(url) { + // XXX + // Since we aren't tracking history yet, replace is the same as assign + this.assign(url); + }), + + reload: constant(function() { + // XXX: + // Actually, the spec is a lot more complicated than this + this.assign(this.href); + }), + + // XXX: Does WebIDL allow the wrapper class to have its own toString + // method? Or do I have to create a proxy just to fake out the string + // conversion? + // In FF, document.location.__proto__.hasOwnProperty("toString") is true + toString: constant(function() { + return this.href; + }), +}); + + + +/************************************************************************ + * src/impl/Window.js + ************************************************************************/ + +//@line 1 "src/impl/Window.js" +// This is a simple constructor for a simple Window implementation +// We'll set things up (in src/main.js for now) so that it unwraps +// to the global object +function Window() { + this.document = new impl.DOMImplementation().createHTMLDocument(""); + this.document._scripting_enabled = true; + this.document.defaultView = this; + this.location = new Location(this, "about:blank"); +} + +Window.prototype = O.create(impl.EventTarget.prototype, { + _idlName: constant("Window"), + + history: constant({ + back: nyi, + forward: nyi, + go: nyi, + _idlName: "History" + }), + + navigator: constant({ + appName: "dom.js", + appVersion: "0.1", + platform: "JavaScript!", + userAgent: "Servo", + _idlName: "Navigator" + }), + + // Self-referential properties + window: attribute(function() { return this; }), + self: attribute(function() { return this; }), + frames: attribute(function() { return this; }), + + // Self-referential properties for a top-level window + parent: attribute(function() { return this; }), + top: attribute(function() { return this; }), + + // We don't support any other windows for now + length: constant(0), // no frames + frameElement: constant(null), // not part of a frame + opener: constant(null), // not opened by another window + + // The onload event handler. + // XXX: need to support a bunch of other event types, too, + // and have them interoperate with document.body. + + onload: attribute( + function() { + return this._getEventHandler("load"); + }, + function(v) { + this._setEventHandler("load", v); + } + ), + + +}); + + + +/************************************************************************ + * src/main.js + ************************************************************************/ + +//@line 1 "src/main.js" +/* +// The document object is the entry point to the entire DOM +defineLazyProperty(global, "document", function() { + var doc = new impl.DOMImplementation().createHTMLDocument(""); + doc._scripting_enabled = true; + return wrap(doc); +}); +*/ + +// Create a window implementation object +var w = new Window(); // See src/impl/Window.js + +// Arrange to have it wrap to the global object +// And have the global object unwrap to w +w._idl = global; +wmset(idlToImplMap, global, w); + +// Now define window properties that do the right thing +// For other wrapper types this is automated by tools/idl2domjs +// but the window object is a special case. + +[ + "window", + "self", + "frames", + "parent", + "top", + "opener", + "document", + "history", + "navigator" +].forEach(function(property) { + Object.defineProperty(global, property, { + get: function() { + return wrap(unwrap(this)[property]); + }, + enumerable: false, + configurable: true, // XXX: check this + }); + }); + +Object.defineProperty(global, "location", { + get: function() { + return wrap(unwrap(this).location); + }, + set: function(v) { + unwrap(this).location.href = v; + }, + enumerable: false, + configurable: true, // XXX: check this +}); + + +Object.defineProperty(global, "onload", { + get: function() { + return unwrap(this).onload; + }, + set: function(v) { + unwrap(this).onload = toCallbackOrNull(v); + }, + enumerable: true, + configurable: true +}); + + +global.addEventListener = function addEventListener(type, listener, capture) { + unwrap(this).addEventListener( + String(type), + toCallbackOrNull(listener), + OptionalBoolean(capture)); +}; + +global.removeEventListener = function addEventListener(type, listener, capture){ + unwrap(this).removeEventListener( + String(type), + toCallbackOrNull(listener), + OptionalBoolean(capture)); +}; + +// XXX +// This is a completely broken implementation put here just to see if we +// can get jQuery animations to work +// +global.getComputedStyle = function getComputedStyle(elt) { + return elt.style; +};}(global)); +}(this)); diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/headless-tests.js b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/headless-tests.js new file mode 100644 index 0000000..a18c806 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/headless-tests.js @@ -0,0 +1,4 @@ +load("dom.js"); +load("nwmatcher.js"); + +var tmp = NW.Dom.select("*", null, function(e) { print(e.nodeName); }); diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/js b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/js new file mode 100755 index 0000000..5131e4a Binary files /dev/null and b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/js differ diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libmozglue.dylib b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libmozglue.dylib new file mode 100755 index 0000000..8af82a8 Binary files /dev/null and b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libmozglue.dylib differ diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libnspr4.dylib b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libnspr4.dylib new file mode 100755 index 0000000..6eea5af Binary files /dev/null and b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libnspr4.dylib differ diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libplc4.dylib b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libplc4.dylib new file mode 100755 index 0000000..f6abcef Binary files /dev/null and b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libplc4.dylib differ diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libplds4.dylib b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libplds4.dylib new file mode 100755 index 0000000..20e5283 Binary files /dev/null and b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/libplds4.dylib differ diff --git a/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/nwmatcher.js b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/nwmatcher.js new file mode 100644 index 0000000..7abd248 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/lib/spidermonkey/nwmatcher.js @@ -0,0 +1,1653 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0beta + * Created: 20070722 + * Release: 20121122 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + // in a Node.js environment, the nwmatcher functions will operate on + // the passed "browserGlobal" and will be returned in an object + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + // in a browser environment, the nwmatcher functions will operate on + // the "global" loading them and be attached to "global.NW.Dom" + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0beta', + + Dom = exports, + + // processing context & root element + doc = global.document, + root = doc.documentElement, + + // save utility methods references + slice = [ ].slice, + string = { }.toString, + + // persist previous parsed data + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + // accepted prefix identifiers + // (id, class & pseudo-class) + prefixes = '[#.:]?', + + // accepted attribute operators + operators = '([~*^$|!]?={1})', + + // accepted whitespace characters + whitespace = '[\\x20\\t\\n\\r\\f]*', + + // 4 combinators F E, F>E, F+E, F~E + combinators = '[\\x20]|[>+~][^>+~]', + + // an+b format params for pseudo-classes + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + // CSS quoted string values + quotedvalue = '"[^"]*"' + "|'[^']*'", + + // skip group of round brackets + skipround = '\\([^()]+\\)|\\(.*\\)', + // skip group of curly brackets + skipcurly = '\\{[^{}]+\\}|\\{.*\\}', + // skip group of square brackets + skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]', + + // skip [ ], ( ), { } groups in token tails + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + // http://www.w3.org/TR/css3-syntax/#characters + // unicode/ISO 10646 characters 161 and higher + // NOTE: Safari 2.0.x crashes with escaped (\\) + // Unicode ranges in regular expressions so we + // use a negated character range class instead + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + + // CSS identifier syntax + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + // build attribute string + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + // build pseudoclass string + pseudoclass = '((?:' + + // an+b parameters or quoted string + pseudoparms + '|' + quotedvalue + '|' + + // id, class, pseudo-class selector + prefixes + '|' + encoding + '+|' + + // nested HTML attribute selector + '\\[' + attributes + '\\]|' + + // nested pseudo-class selector + '\\(.+\\)|' + whitespace + '|' + + // nested pseudos/separators + ',)+)', + + // placeholder for extensions + extensions = '.+', + + // CSS3: syntax scanner and + // one pass validation only + // using regular expression + standardValidator = + // discard start + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + // open match group + '(' + + //universal selector + '\\*' + + // id/class/tag/pseudo-class identifier + '|(?:' + prefixes + identifier + ')' + + // combinator selector + '|' + combinators + + // HTML attribute selector + '|\\[' + attributes + '\\]' + + // pseudo-classes parameters + '|\\(' + pseudoclass + '\\)' + + // dom properties selector (extension) + '|\\{' + extensions + '\\}' + + // selector group separator (comma) + '|(?:,|' + whitespace + ')' + + // close match group + ')+', + + // validator for complex selectors in ':not()' pseudo-classes + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + // validator for standard selectors as default + reValidator = new RegExp(standardValidator, 'g'), + + // whitespace is any combination of these 5 character [\x20\t\n\r\f] + // http://www.w3.org/TR/css3-selectors/#selector-syntax + reTrimSpaces = new RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + // only allow simple selectors nested in ':not()' pseudo-classes + reSimpleNot = new RegExp('^(' + + '(?!:not)' + + '(' + prefixes + + '|' + identifier + + '|\\([^()]*\\))+' + + '|\\[' + attributes + '\\]' + + ')$'), + + // split comma groups, exclude commas from + // quotes '' "" and from brackets () [] {} + reSplitGroup = new RegExp('(' + + '[^,\\\\()[\\]]+' + + '|' + skipsquare + + '|' + skipround + + '|' + skipcurly + + '|\\\\.' + + ')+', 'g'), + + // split last, right most, selector group token + reSplitToken = new RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20>+~]|\\\\.)+', 'g'), + + // for in excess whitespace removal + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = new RegExp(identifier + '|^$'), + + /*----------------------------- FEATURE TESTING ----------------------------*/ + + // detect native methods + isNative = (function() { + var s = (doc.appendChild + '').replace(/appendChild/g, ''); + return function(object, method) { + var m = object && object[method] || false; + return m && typeof m != 'string' && + s == (m + '').replace(new RegExp(method, 'g'), ''); + }; + })(), + + // NATIVE_XXXXX true if method exist and is callable + // detect if DOM methods are native in browsers + NATIVE_FOCUS = isNative(doc, 'hasFocus'), + NATIVE_QSAPI = isNative(doc, 'querySelector'), + NATIVE_GEBID = isNative(doc, 'getElementById'), + NATIVE_GEBTN = isNative(root, 'getElementsByTagName'), + NATIVE_GEBCN = isNative(root, 'getElementsByClassName'), + + // detect native getAttribute/hasAttribute methods, + // frameworks extend these to elements, but it seems + // this does not work for XML namespaced attributes, + // used to check both getAttribute/hasAttribute in IE + NATIVE_GET_ATTRIBUTE = isNative(root, 'getAttribute'), + NATIVE_HAS_ATTRIBUTE = isNative(root, 'hasAttribute'), + + // check if slice() can convert nodelist to array + // see http://yura.thinkweb2.com/cft/ + NATIVE_SLICE_PROTO = + (function() { + var isBuggy = false, id = root.id; + root.id = 'length'; + try { + isBuggy = !!slice.call(doc.childNodes, 0)[0]; + } catch(e) { } + root.id = id; + return isBuggy; + })(), + + // supports the new traversal API + NATIVE_TRAVERSAL_API = + 'nextElementSibling' in root && 'previousElementSibling' in root, + + // BUGGY_XXXXX true if method is feature tested and has known bugs + // detect buggy gEBID + BUGGY_GEBID = NATIVE_GEBID ? + (function() { + var isBuggy = true, x = 'x' + String(+new Date), + a = doc.createElementNS ? 'a' : '
    '; + (a = doc.createElement(a)).name = x; + root.insertBefore(a, root.firstChild); + isBuggy = !!doc.getElementById(x); + root.removeChild(a); + return isBuggy; + })() : + true, + + // detect IE gEBTN comment nodes bug + BUGGY_GEBTN = NATIVE_GEBTN ? + (function() { + var div = doc.createElement('div'); + div.appendChild(doc.createComment('')); + return !!div.getElementsByTagName('*')[0]; + })() : + true, + + // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2 + // caching class name results and not detecting when changed, + // tests are based on the jQuery selector test suite + BUGGY_GEBCN = NATIVE_GEBCN ? + (function() { + var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317'; + + // Opera tests + div.appendChild(doc.createElement('span')). + setAttribute('class', test + 'abc ' + test); + div.appendChild(doc.createElement('span')). + setAttribute('class', 'x'); + + isBuggy = !div.getElementsByClassName(test)[0]; + + // Safari test + div.lastChild.className = test; + return isBuggy || div.getElementsByClassName(test).length != 2; + })() : + true, + + // detect IE bug with dynamic attributes + BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ? + (function() { + var input = doc.createElement('input'); + input.setAttribute('value', 5); + return input.defaultValue != 5; + })() : + true, + + // detect IE bug with non-standard boolean attributes + BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ? + (function() { + var option = doc.createElement('option'); + option.setAttribute('selected', 'selected'); + return !option.hasAttribute('selected'); + })() : + true, + + // detect Safari bug with selected option elements + BUGGY_SELECTED = + (function() { + var select = doc.createElement('select'); + select.appendChild(doc.createElement('option')); + return !select.firstChild.selected; + })(), + + // initialized with the loading context + // and reset for each different context + BUGGY_QUIRKS_GEBCN, + BUGGY_QUIRKS_QSAPI, + + QUIRKS_MODE, + XML_DOCUMENT, + + // detect Opera browser + OPERA = /opera/i.test(string.call(global.opera)), + + // skip simpe selector optimizations for Opera >= 11 + OPERA_QSAPI = OPERA && parseFloat(opera.version()) >= 11, + + // check Seletor API implementations + RE_BUGGY_QSAPI = NATIVE_QSAPI ? + (function() { + var pattern = [ ], div = doc.createElement('div'), element, + + expect = function(selector, context, element, n) { + var result = false; + context.appendChild(element); + try { result = context.querySelectorAll(selector).length == n; } catch(e) { } + while (context.firstChild) { context.removeChild(context.firstChild); } + return result; + }; + + // ^= $= *= operators bugs whith empty values (Opera 10 / IE8) + element = doc.createElement('p'); + element.setAttribute('class', ''); + expect('[class^=""]', div, element, 1) && + pattern.push('[*^$]=[\\x20\\t\\n\\r\\f]*(?:""|' + "'')"); + + // :checked bug with option elements (Firefox 3.6.x) + // it wrongly includes 'selected' options elements + // HTML5 rules says selected options also match + element = doc.createElement('option'); + element.setAttribute('selected', 'selected'); + expect(':checked', div, element, 0) && + pattern.push(':checked'); + + // :enabled :disabled bugs with hidden fields (Firefox 3.5 QSA bug) + // http://www.w3.org/TR/html5/interactive-elements.html#selector-enabled + // IE8 QSA has problems too and throws error with these dynamic pseudos + element = doc.createElement('input'); + element.setAttribute('type', 'hidden'); + expect(':enabled', div, element, 0) && + pattern.push(':enabled', ':disabled'); + + // :link bugs with hyperlinks matching (Firefox/Safari) + element = doc.createElement('link'); + element.setAttribute('href', 'x'); + expect(':link', div, element, 1) || + pattern.push(':link'); + + // avoid attribute selectors for IE QSA + if (BUGGY_HAS_ATTRIBUTE) { + // IE fails in reading: + // - original values for input/textarea + // - original boolean values for controls + pattern.push('\\[[\\x20\\t\\n\\r\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)'); + } + + return pattern.length ? + new RegExp(pattern.join('|')) : + { 'test': function() { return false; } }; + + })() : + true, + + // matches class selectors + RE_CLASS = new RegExp('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')'), + + // matches simple id, tag & class selectors + RE_SIMPLE_SELECTOR = new RegExp( + !(BUGGY_GEBTN && BUGGY_GEBCN) ? !OPERA ? + '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^(?:\\*|#-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^#?-?[_a-zA-Z]{1}' + encoding + '*$'), + + /*----------------------------- LOOKUP OBJECTS -----------------------------*/ + + LINK_NODES = { 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 }, + + // boolean attributes should return attribute name instead of true/false + ATTR_BOOLEAN = { + 'checked': 1, 'disabled': 1, 'ismap': 1, + 'multiple': 1, 'readonly': 1, 'selected': 1 + }, + + // dynamic attributes that needs to be checked against original HTML value + ATTR_DEFAULT = { + 'value': 'defaultValue', + 'checked': 'defaultChecked', + 'selected': 'defaultSelected' + }, + + // attribute referencing URI data values need special treatment in IE + ATTR_URIDATA = { + 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2, + 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2 + }, + + // HTML 5 draft specifications + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + HTML_TABLE = { + // class attribute must be treated case-insensitive in HTML quirks mode + // initialized by default to Standard Mode (case-sensitive), + // set dynamically by the attribute resolver + 'class': 0, + 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, + 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, + 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, + 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, + 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, + 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, + 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 + }, + + // the following attributes must be treated case-insensitive in XHTML mode + // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity + XHTML_TABLE = { + 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1, + 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1, + 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1, + 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1 + }, + + /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/ + + // placeholder to add functionalities + Selectors = { + // as a simple example this will check + // for chars not in standard ascii table + // + // 'mySpecialSelector': { + // 'Expression': /\u0080-\uffff/, + // 'Callback': mySelectorCallback + // } + // + // 'mySelectorCallback' will be invoked + // only after passing all other standard + // checks and only if none of them worked + }, + + // attribute operators + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + // optimization expressions + Optimize = { + ID: new RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: new RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: new RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + // precompiled Regular Expressions + Patterns = { + // structural pseudo-classes and child selectors + spseudos: /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i, + // uistates + dynamic + negation pseudo-classes + dpseudos: /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i, + // element attribute matcher + attribute: new RegExp('^\\[' + attrmatcher + '\\](.*)'), + // E > F + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + // E + F + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + // E ~ F + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + // E F + ancestor: /^[\x20\t\n\r\f]+(.*)/, + // all + universal: /^\*(.*)/, + // id + id: new RegExp('^#(' + encoding + '+)(.*)'), + // tag + tagName: new RegExp('^(' + encoding + '+)(.*)'), + // class + className: new RegExp('^\\.(' + encoding + '+)(.*)') + }, + + /*------------------------------ UTIL METHODS ------------------------------*/ + + // concat elements to data + concatList = + function(data, elements) { + var i = -1, element; + if (!data.length && Array.slice) + return Array.slice(elements); + while ((element = elements[++i])) + data[data.length] = element; + return data; + }, + + // concat elements to data and callback + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + // change context specific variables + switchContext = + function(from, force) { + var div, oldDoc = doc; + // save passed context + lastContext = from; + // set new context document + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + // set document root + root = doc.documentElement; + // set host environment flags + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + + // In quirks mode css class names are case insensitive. + // In standards mode they are case sensitive. See docs: + // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = doc.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + div = doc.createElement('div'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx'); + + // GEBCN buggy in quirks mode, match count is: + // Firefox 3.0+ [xxx = 1, xXx = 1] + // Opera 10.63+ [xxx = 0, xXx = 2] + BUGGY_QUIRKS_GEBCN = + !XML_DOCUMENT && NATIVE_GEBCN && QUIRKS_MODE && + (div.getElementsByClassName('xxx').length != 2 || + div.getElementsByClassName('xXx').length != 2); + + // QSAPI buggy in quirks mode, match count is: + // At least Chrome 4+, Firefox 3.5+, Opera 10.x+, Safari 4+ [xxx = 1, xXx = 2] + // Safari 3.2 QSA doesn't work with mixedcase in quirksmode [xxx = 1, xXx = 0] + // https://bugs.webkit.org/show_bug.cgi?id=19047 + // must test the attribute selector '[class~=xxx]' + // before '.xXx' or the bug may not present itself + BUGGY_QUIRKS_QSAPI = + !XML_DOCUMENT && NATIVE_QSAPI && QUIRKS_MODE && + (div.querySelectorAll('[class~=xxx]').length != 2 || + div.querySelectorAll('.xXx').length != 2); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + /*------------------------------ DOM METHODS -------------------------------*/ + + // element by id (raw) + // @return reference or null + byIdRaw = + function(id, elements) { + var i = -1, element = null; + while ((element = elements[++i])) { + if (element.getAttribute('id') == id) { + break; + } + } + return element; + }, + + // element by id + // @return reference or null + _byId = !BUGGY_GEBID ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + // publicly exposed byId + // @return reference or null + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + // elements by tag (raw) + // @return array + byTagRaw = + function(tag, from) { + var any = tag == '*', element = from, elements = [ ], next = element.firstChild; + any || (tag = tag.toUpperCase()); + while ((element = next)) { + if (element.tagName > '@' && (any || element.tagName.toUpperCase() == tag)) { + elements[elements.length] = element; + } + if ((next = element.firstChild || element.nextSibling)) continue; + while (!next && (element = element.parentNode) && element !== from) { + next = element.nextSibling; + } + } + return elements; + }, + + // elements by tag + // @return array + _byTag = !BUGGY_GEBTN && NATIVE_SLICE_PROTO ? + function(tag, from) { + return XML_DOCUMENT || from.nodeType == 11 ? byTagRaw(tag, from) : + slice.call(from.getElementsByTagName(tag), 0); + } : + function(tag, from) { + var i = -1, j = i, data = [ ], + element, elements = from.getElementsByTagName(tag); + if (tag == '*') { + while ((element = elements[++i])) { + if (element.nodeName > '@') + data[++j] = element; + } + } else { + while ((element = elements[++i])) { + data[i] = element; + } + } + return data; + }, + + // publicly exposed byTag + // @return array + byTag = + function(tag, from) { + switchContext(from || (from = doc)); + return _byTag(tag, from); + }, + + // publicly exposed byName + // @return array + byName = + function(name, from) { + return select('[name="' + name.replace(/\\/g, '') + '"]', from); + }, + + // elements by class (raw) + // @return array + byClassRaw = + function(name, from) { + var i = -1, j = i, data = [ ], element, elements = _byTag('*', from), n; + name = ' ' + (QUIRKS_MODE ? name.toLowerCase() : name).replace(/\\/g, '') + ' '; + while ((element = elements[++i])) { + n = XML_DOCUMENT ? element.getAttribute('class') : element.className; + if (n && n.length && (' ' + (QUIRKS_MODE ? n.toLowerCase() : n). + replace(reWhiteSpace, ' ') + ' ').indexOf(name) > -1) { + data[++j] = element; + } + } + return data; + }, + + // elements by class + // @return array + _byClass = + function(name, from) { + return (BUGGY_GEBCN || BUGGY_QUIRKS_GEBCN || XML_DOCUMENT || !from.getElementsByClassName) ? + byClassRaw(name, from) : slice.call(from.getElementsByClassName(name.replace(/\\/g, '')), 0); + }, + + // publicly exposed byClass + // @return array + byClass = + function(name, from) { + switchContext(from || (from = doc)); + return _byClass(name, from); + }, + + // check element is descendant of container + // @return boolean + contains = 'compareDocumentPosition' in root ? + function(container, element) { + return (container.compareDocumentPosition(element) & 16) == 16; + } : 'contains' in root ? + function(container, element) { + return container !== element && container.contains(element); + } : + function(container, element) { + while ((element = element.parentNode)) { + if (element === container) return true; + } + return false; + }, + + // attribute value + // @return string + getAttribute = !BUGGY_GET_ATTRIBUTE ? + function(node, attribute) { + return node.getAttribute(attribute) || ''; + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return node[ATTR_DEFAULT[attribute]] || ''; + } + return ( + // specific URI data attributes (parameter 2 to fix IE bug) + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + // boolean attributes should return name instead of true/false + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : '' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + // attribute presence + // @return boolean + hasAttribute = !BUGGY_HAS_ATTRIBUTE ? + function(node, attribute) { + return XML_DOCUMENT ? + !!node.getAttribute(attribute) : + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + // need to get at AttributeNode first on IE + node = node.getAttributeNode(attribute); + // use both "specified" & "nodeValue" properties + return !!(node && (node.specified || node.nodeValue)); + }, + + // check node emptyness + // @return boolean + isEmpty = + function(node) { + node = node.firstChild; + while (node) { + if (node.nodeType == 3 || node.nodeName > '@') return false; + node = node.nextSibling; + } + return true; + }, + + // check if element matches the :link pseudo + // @return boolean + isLink = + function(element) { + return hasAttribute(element,'href') && LINK_NODES[element.nodeName]; + }, + + // child position by nodeType + // @return number + nthElement = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling'; + while ((element = element[succ])) { + if (element.nodeName > '@') ++count; + } + return count; + }, + + // child position by nodeName + // @return number + nthOfType = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName; + while ((element = element[succ])) { + if (element.nodeName == type) ++count; + } + return count; + }, + + /*------------------------------- DEBUGGING --------------------------------*/ + + // get/set (string/object) working modes + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + Config['USE_QSAPI'] = false; + reValidator = new RegExp(extendedValidator, 'g'); + } else if (i == 'USE_QSAPI') { + Config[i] = !!option[i] && NATIVE_QSAPI; + reValidator = new RegExp(standardValidator, 'g'); + } + } + return true; + }, + + // control user notifications + emit = + function(message) { + message = 'SYNTAX_ERR: ' + message + ' '; + if (Config.VERBOSITY) { + throw new SyntaxError(message); + } else { + if (global.console && global.console.log) { + global.console.log(message); + } else { + global.status += message; + } + } + }, + + Config = { + + // used to enable/disable caching of result sets + CACHING: false, + + // by default do not add missing left/right context + // to selector string shortcuts like "+div" or "ul>" + // callable Dom.shortcuts method has to be available + SHORTCUTS: false, + + // by default disable complex selectors nested in + // ':not()' pseudo-classes, as for specifications + SIMPLENOT: true, + + // HTML5 handling for the ":checked" pseudo-class + USE_HTML5: true, + + // controls enabling the Query Selector API branch + USE_QSAPI: NATIVE_QSAPI, + + // controls the engine error/warning notifications + VERBOSITY: true + + }, + + /*---------------------------- COMPILER METHODS ----------------------------*/ + + // code string reused to build compiled functions + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + + // compile a comma separated group of selector + // @mode boolean true for select, false for match + // return a compiled function + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + // ensures that source is a string + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + // for each selector in the group + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + // avoid repeating the same token + // in comma separated group (p, p) + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) { + // for select method + return new Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + } else { + // for match method + return new Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + } + }, + + // allows to cache already visited nodes + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + // compile a CSS3 string selector into ad-hoc javascript matching function + // @return string (to be compiled) + compileSelector = + function(selector, source, mode) { + + var a, b, n, k = 0, expr, match, result, status, test, type; + + while (selector) { + + k++; + + // *** Universal selector + // * match all (empty block, do not remove) + if ((match = selector.match(Patterns.universal))) { + // do nothing, handled in the compiler where + // BUGGY_GEBTN return comment nodes (ex: IE) + expr = ''; + } + + // *** ID selector + // #Foo Id case sensitive + else if ((match = selector.match(Patterns.id))) { + // document can contain conflicting elements (id/name) + // prototype selector unit need this method to recover bad HTML forms + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + // *** Type selector + // Foo Tag (case insensitive) + else if ((match = selector.match(Patterns.tagName))) { + // both tagName and nodeName properties may be upper/lower case + // depending on their creation NAMESPACE in createElementNS() + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : '.toUpperCase()' + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + // *** Class selector + // .Foo Class (case sensitive) + else if ((match = selector.match(Patterns.className))) { + // W3C CSS3 specs: element whose "class" attribute has been assigned a + // list of whitespace-separated values, see section 6.4 Class selectors + // and notes at the bottom; explicitly non-normative in this specification. + source = 'if((n=' + (XML_DOCUMENT ? + 's.getAttribute(e,"class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + // *** Attribute selector + // [attr] [attr=value] [attr="value"] [attr='value'] and !=, *=, ~=, |=, ^=, $= + // case sensitivity is treated differently depending on the document type (see map) + else if ((match = selector.match(Patterns.attribute))) { + + // xml namespaced attribute ? + expr = match[1].split(':'); + expr = expr.length == 2 ? expr[1] : expr[0] + ''; + + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + + test = false; + type = 'false'; + + // replace Operators parameter if needed + if (match[2] && match[4] && (type = Operators[match[2]])) { + // case treatment depends on document + HTML_TABLE['class'] = QUIRKS_MODE ? 1 : 0; + // replace escaped values and HTML entities + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/, '\\x$1'); + test = (XML_DOCUMENT ? XHTML_TABLE : HTML_TABLE)[expr.toLowerCase()]; + type = type.replace(/\%m/g, test ? match[4].toLowerCase() : match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + type = 'n' + match[2] + '="' + match[4] + '"'; + } + + // build expression for has/getAttribute + expr = 'n=s.' + (match[2] ? 'get' : 'has') + + 'Attribute(e,"' + match[1] + '")' + + (test ? '.toLowerCase();' : ';'); + + source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}'; + } + + // *** Adjacent sibling combinator + // E + F (F adiacent sibling of E) + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + 'var N' + k + '=e;while(e&&(e=e.previousElementSibling)){' + source + 'break;}e=N' + k + ';' : + 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + // *** General sibling combinator + // E ~ F (F relative sibling of E) + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + ('var N' + k + '=e;e=e.parentNode.firstElementChild;' + + 'while(e&&e!==N' + k + '){' + source + 'e=e.nextElementSibling;}e=N' + k + ';') : + ('var N' + k + '=e;e=e.parentNode.firstChild;' + + 'while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'); + } + + // *** Child combinator + // E > F (F children of E) + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + // *** Descendant combinator + // E F (E ancestor of F) + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + // *** Structural pseudo-classes + // :root, :empty, + // :first-child, :last-child, :only-child, + // :first-of-type, :last-of-type, :only-of-type, + // :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-of-type() + else if ((match = selector.match(Patterns.spseudos)) && match[1]) { + + switch (match[1]) { + case 'root': + // element root of the document + if (match[3]) { + source = 'if(e===h||s.contains(h,e)){' + source + '}'; + } else { + source = 'if(e===h){' + source + '}'; + } + break; + + case 'empty': + // element that has no children + source = 'if(s.isEmpty(e)){' + source + '}'; + break; + + default: + if (match[1] && match[2]) { + if (match[2] == 'n') { + source = 'if(e!==h){' + source + '}'; + break; + } else if (match[2] == 'even') { + a = 2; + b = 0; + } else if (match[2] == 'odd') { + a = 2; + b = 1; + } else { + // assumes correct "an+b" format, "b" before "a" to keep "n" values + b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0); + a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0); + if (n && n[1] == '-') a = -1; + } + + // build test expression out of structural pseudo (an+b) parameters + // see here: http://www.w3.org/TR/css3-selectors/#nth-child-pseudo + test = a > 1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ? + 'n==' + b : + (/last/i.test(match[1])) ? + a == -1 ? 'n>=' + b : 'n<=' + b : + a == -1 ? 'n<=' + b : 'n>=' + b; + + // 4 cases: 1 (nth) x 4 (child, of-type, last-child, last-of-type) + source = + 'if(e!==h){' + + 'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' + + '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' + + 'if(' + test + '){' + source + '}' + + '}'; + + } else { + // 6 cases: 3 (first, last, only) x 1 (child) x 2 (-of-type) + a = /first/i.test(match[1]) ? 'previous' : 'next'; + n = /only/i.test(match[1]) ? 'previous' : 'next'; + b = /first|last/i.test(match[1]); + + type = /of-type/i.test(match[1]) ? '&&n.nodeName!=e.nodeName' : '&&n.nodeName<"@"'; + source = 'if(e!==h){' + + ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source : + 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}'; + } + break; + } + + } + + // *** negation, user action and target pseudo-classes + // *** UI element states and dynamic pseudo-classes + // CSS3 :not, :checked, :enabled, :disabled, :target + // CSS3 :active, :hover, :focus + // CSS3 :link, :visited + else if ((match = selector.match(Patterns.dpseudos)) && match[1]) { + + switch (match[1].match(/^\w+/)[0]) { + // CSS3 negation pseudo-class + case 'not': + // compile nested selectors, DO NOT pass the callback parameter + // SIMPLENOT allow disabling complex selectors nested + // in ':not()' pseudo-classes, breaks some test units + expr = match[3].replace(reTrimSpaces, ''); + + if (Config.SIMPLENOT && !reSimpleNot.test(expr)) { + // see above, log error but continue execution + emit('Negation pseudo-class only accepts simple selectors "' + selector + '"'); + return ''; + } else { + if ('compatMode' in doc) { + source = 'if(!' + compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}'; + } else { + source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}'; + } + } + break; + + // CSS3 UI element states + case 'checked': + // for radio buttons checkboxes (HTML4) and options (HTML5) + source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' + + (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') + + '){' + source + '}'; + break; + case 'disabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===true){' + source + '}'; + break; + case 'enabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===false){' + source + '}'; + break; + + // CSS3 lang pseudo-class + case 'lang': + test = ''; + if (match[2]) test = match[2].substr(0, 2) + '-'; + source = 'do{(n=e.lang||"").toLowerCase();' + + 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' + + '(n&&(n=="' + match[2].toLowerCase() + + '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' + + '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);'; + break; + + // CSS3 target pseudo-class + case 'target': + n = doc.location ? doc.location.hash : ''; + if (n) { + source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}'; + } + break; + + // CSS3 dynamic pseudo-classes + case 'link': + source = 'if(s.isLink(e)&&!e.visited){' + source + '}'; + break; + case 'visited': + source = 'if(s.isLink(e)&&e.visited){' + source + '}'; + break; + + // CSS3 user action pseudo-classes IE & FF3 have native support + // these capabilities may be emulated by some event managers + case 'active': + if (XML_DOCUMENT) break; + source = 'if(e===d.activeElement){' + source + '}'; + break; + case 'hover': + if (XML_DOCUMENT) break; + source = 'if(e===d.hoverElement){' + source + '}'; + break; + case 'focus': + if (XML_DOCUMENT) break; + source = NATIVE_FOCUS ? + 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' : + 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}'; + break; + + // CSS2 selected pseudo-classes, not part of current CSS3 drafts + // the 'selected' property is only available for option elements + case 'selected': + // fix Safari selectedIndex property bug + expr = BUGGY_SELECTED ? '||(n=e.parentNode)&&n.options[n.selectedIndex]===e' : ''; + source = 'if(/^option$/i.test(e.nodeName)&&(e.selected' + expr + ')){' + source + '}'; + break; + + default: + break; + } + + } + + else { + + // this is where external extensions are + // invoked if expressions match selectors + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + // if an extension fails to parse the selector + // it must return a false boolean in "status" + if (!status) { + // log error but continue execution, don't throw real exceptions + // because blocking following processes maybe is not a good idea + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + // see above, log error but continue execution + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + // error if no matches found by the pattern scan + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + // ensure "match" is not null or empty since + // we do not throw real DOMExceptions above + selector = match && match[match.length - 1]; + } + + return source; + }, + + /*----------------------------- QUERY METHODS ------------------------------*/ + + // match element with selector + // @return boolean + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (from && from.nodeType == 1 && !contains(from, element)) { + return false; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + // compile matcher resolver if necessary + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + // select only the first element + // matching selector (document ordered) + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + // select elements matching selector + // using new Query Selector API + // or cross-browser client API + // @return array + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Missing required selector parameters'); + return [ ]; + } else if (selector === '') { + emit('Empty selector string'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid context element'); + return [ ]; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + if (!OPERA_QSAPI && RE_SIMPLE_SELECTOR.test(selector)) { + switch (selector.charAt(0)) { + case '#': + if ((element = _byId(selector.slice(1), from))) { + elements = [ element ]; + } else elements = [ ]; + break; + case '.': + elements = _byClass(selector.slice(1), from); + break; + default: + elements = _byTag(selector, from); + break; + } + } + + else if (!XML_DOCUMENT && Config.USE_QSAPI && + !(BUGGY_QUIRKS_QSAPI && RE_CLASS.test(selector)) && + !RE_BUGGY_QSAPI.test(selector)) { + try { + elements = from.querySelectorAll(selector); + } catch(e) { } + } + + if (elements) { + elements = callback ? concatCall([ ], elements, callback) : + NATIVE_SLICE_PROTO ? slice.call(elements) : concatList([ ], elements); + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + // commas separators are treated sequentially to maintain order + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (!XML_DOCUMENT && isSingleSelect) { + + if (changed) { + // get right most selector token + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + + // only last slice before :not rules + lastSlice = token.split(':not')[0]; + + // position where token was found + lastPosition = selector.length - token.length; + } + + // ID optimization RTL, to reduce number of elements to visit + if ((parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + // ID optimization LTR, to reduce selection context searches + else if ((parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { +// selector = selector.replace('#' + token, '*'); +// lastPosition -= token.length + 1; + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if ((parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if ((parts = selector.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + for (i = 0, els = [ ]; elements.length > i; ++i) { + els = concatList(els, elements[i].getElementsByTagName('*')); + } + elements = els; + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if (NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + } + + if (!elements) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? from.childNodes : _byTag('*', from); + } + // end of prefiltering pass + + // compile selector resolver if necessary + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, '', true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + /*-------------------------------- STORAGE ---------------------------------*/ + + // compiled match functions returning booleans + matchContexts = { }, + matchResolvers = { }, + + // compiled select functions returning collections + selectContexts = { }, + selectResolvers = { }, + + // used to pass methods to compiled functions + Snapshot = { + + // element indexing methods + nthElement: nthElement, + nthOfType: nthOfType, + + // element inspection methods + getAttribute: getAttribute, + hasAttribute: hasAttribute, + + // element selection methods + byClass: _byClass, + byName: byName, + byTag: _byTag, + byId: _byId, + + // helper/check methods + contains: contains, + isEmpty: isEmpty, + isLink: isLink, + + // selection/matching + select: select, + match: match + }, + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + /*------------------------------- PUBLIC API -------------------------------*/ + + // code referenced by extensions + Dom.ACCEPT_NODE = ACCEPT_NODE; + + // log resolvers errors/warnings + Dom.emit = emit; + + // retrieve element by id attr + Dom.byId = byId; + + // retrieve elements by tag name + Dom.byTag = byTag; + + // retrieve elements by name attr + Dom.byName = byName; + + // retrieve elements by class name + Dom.byClass = byClass; + + // read the value of the attribute + // as was in the original HTML code + Dom.getAttribute = getAttribute; + + // check for the attribute presence + // as was in the original HTML code + Dom.hasAttribute = hasAttribute; + + // element match selector, return boolean true/false + Dom.match = match; + + // first element match only, return element or null + Dom.first = first; + + // elements matching selector, starting from element + Dom.select = select; + + // compile selector into ad-hoc javascript resolver + Dom.compile = compile; + + // check that two elements are ancestor/descendant + Dom.contains = contains; + + // handle selector engine configuration settings + Dom.configure = configure; + + // initialize caching for each document + Dom.setCache = function() { return; }; + + // load previously collected result set + Dom.loadResults = function() { return; }; + + // save previously collected result set + Dom.saveResults = function() { return; }; + + // handle missing context in selector strings + Dom.shortcuts = function(x) { return x; }; + + // options enabing specific engine functionality + Dom.Config = Config; + + // pass methods references to compiled resolvers + Dom.Snapshot = Snapshot; + + // operators descriptor + // for attribute operators extensions + Dom.Operators = Operators; + + // selectors descriptor + // for pseudo-class selectors extensions + Dom.Selectors = Selectors; + + // export string patterns + Dom.Tokens = Tokens; + + // add or overwrite user defined operators + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + // add selector patterns for user defined callbacks + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + /*---------------------------------- INIT ----------------------------------*/ + + // init context specific variables + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/package.json b/node_modules/jsdom/node_modules/nwmatcher/package.json new file mode 100644 index 0000000..8a8a5a8 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/package.json @@ -0,0 +1,45 @@ +{ + "name": "nwmatcher", + "version": "1.3.0", + "description": "A CSS3-compliant JavaScript selector engine.", + "homepage": "http://javascript.nwbox.com/NWMatcher/", + "main": "./src/nwmatcher", + "keywords": [ + "css", + "matcher", + "selector", + "ender" + ], + "licenses": [ + { + "type": "MIT", + "url": "http://javascript.nwbox.com/NWMatcher/MIT-LICENSE" + } + ], + "author": { + "name": "Diego Perini", + "email": "diego.perini@gmail.com", + "url": "http://www.iport.it/" + }, + "maintainers": [ + { + "name": "Diego Perini", + "email": "diego.perini@gmail.com", + "url": "http://www.iport.it/" + } + ], + "bugs": { + "url": "http://github.com/dperini/nwmatcher/issues" + }, + "repository": { + "type": "git", + "url": "git://github.com/dperini/nwmatcher.git" + }, + "ender": "./lib/ender/bridge.js", + "readme": "ERROR: No README.md file found!", + "_id": "nwmatcher@1.3.0", + "dist": { + "shasum": "d4fd64d241510ee6f3861b77a71fc9243143c116" + }, + "_from": "nwmatcher@>=1.3.0" +} diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/NEW/nwmatcher-base.js b/node_modules/jsdom/node_modules/nwmatcher/src/NEW/nwmatcher-base.js new file mode 100644 index 0000000..c92303f --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/NEW/nwmatcher-base.js @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0beta + * Created: 20070722 + * Release: 20121122 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0beta', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + REFLECTED = { 'value': 1, 'checked': 1, 'selected': 1 }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + if (Config.SIMPLENOT) { + reValidator = RegExp(standardValidator, 'g'); + } else { + reValidator = RegExp(extendedValidator, 'g'); + } + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + message = 'SYNTAX_ERR: ' + message + ' '; + if (Config.VERBOSITY) { + throw SyntaxError(message); + } else { + if (global.console && global.console.log) { + global.console.log(message); + } else { + global.status += message; + } + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttr = + function(node, attribute) { + return ( + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ((node = node.attributes[attribute]) && node.value) || ''); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttr(e,"id")' : + '(e.submit?s.getAttr(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + name = match[1].toLowerCase(); + if (match[2] && match[4] && (type = Operators[match[2]])) { + test = name in INSENSITIVE_MAP; + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/, '\\x$1'); + type = type.replace(/\%m/g, match[4].toLowerCase()); + expr = 'n=s.getAttr(e,"' + name + '").toLowerCase();'; + } else if (!match[2]) { + if (REFLECTED[name]) { + test = 'default' + name.charAt(0).toUpperCase() + name.slice(1); + expr = 'n=e["' + test + '"];'; + type = 'n'; + } else { + expr = 'n=e.attributes["' + name + '"];'; + type = IE_LT_9 ? 'n&&n.specified' : 'n'; + } + } else if (match[2] == '!=' || match[2] == '=') { + expr = 'n=e.attributes["' + name + '"];'; + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + type = 'n&&n.value' + match[2] + '="' + match[4] + '"'; + } else { + expr = ''; + type = 'false'; + } + source = expr + 'if(' + type + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Missing required selector parameters'); + return [ ]; + } else if (selector === '') { + emit('Empty selector string'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if ((parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if ((parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\/g, ''))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttr: getAttr + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + Dom.Operators = Operators; + Dom.Selectors = Selectors; + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.setCache = function() { return; }; + Dom.loadResults = function() { return; }; + Dom.saveResults = function() { return; }; + + Dom.shortcuts = function(x) { return x; }; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/NEW/nwmatcher.js b/node_modules/jsdom/node_modules/nwmatcher/src/NEW/nwmatcher.js new file mode 100644 index 0000000..147bf31 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/NEW/nwmatcher.js @@ -0,0 +1,1655 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0beta + * Created: 20070722 + * Release: 20121122 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + // in a Node.js environment, the nwmatcher functions will operate on + // the passed "browserGlobal" and will be returned in an object + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + // in a browser environment, the nwmatcher functions will operate on + // the "global" loading them and be attached to "global.NW.Dom" + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0beta', + + Dom = exports, + + // processing context & root element + doc = global.document, + root = doc.documentElement, + + // save utility methods references + slice = [ ].slice, + string = { }.toString, + + // persist previous parsed data + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + // accepted prefix identifiers + // (id, class & pseudo-class) + prefixes = '[#.:]?', + + // accepted attribute operators + operators = '([~*^$|!]?={1})', + + // accepted whitespace characters + whitespace = '[\\x20\\t\\n\\r\\f]*', + + // 4 combinators F E, F>E, F+E, F~E + combinators = '[\\x20]|[>+~][^>+~]', + + // an+b format params for pseudo-classes + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + // CSS quoted string values + quotedvalue = '"[^"]*"' + "|'[^']*'", + + // skip group of round brackets + skipround = '\\([^()]+\\)|\\(.*\\)', + // skip group of curly brackets + skipcurly = '\\{[^{}]+\\}|\\{.*\\}', + // skip group of square brackets + skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]', + + // skip [ ], ( ), { } groups in token tails + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + // http://www.w3.org/TR/css3-syntax/#characters + // unicode/ISO 10646 characters 161 and higher + // NOTE: Safari 2.0.x crashes with escaped (\\) + // Unicode ranges in regular expressions so we + // use a negated character range class instead + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + + // CSS identifier syntax + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + // build attribute string + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + // build pseudoclass string + pseudoclass = '((?:' + + // an+b parameters or quoted string + pseudoparms + '|' + quotedvalue + '|' + + // id, class, pseudo-class selector + prefixes + '|' + encoding + '+|' + + // nested HTML attribute selector + '\\[' + attributes + '\\]|' + + // nested pseudo-class selector + '\\(.+\\)|' + whitespace + '|' + + // nested pseudos/separators + ',)+)', + + // placeholder for extensions + extensions = '.+', + + // CSS3: syntax scanner and + // one pass validation only + // using regular expression + standardValidator = + // discard start + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + // open match group + '(' + + //universal selector + '\\*' + + // id/class/tag/pseudo-class identifier + '|(?:' + prefixes + identifier + ')' + + // combinator selector + '|' + combinators + + // HTML attribute selector + '|\\[' + attributes + '\\]' + + // pseudo-classes parameters + '|\\(' + pseudoclass + '\\)' + + // dom properties selector (extension) + '|\\{' + extensions + '\\}' + + // selector group separator (comma) + '|(?:,|' + whitespace + ')' + + // close match group + ')+', + + // validator for complex selectors in ':not()' pseudo-classes + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + // validator for standard selectors as default + reValidator = new RegExp(standardValidator, 'g'), + + // whitespace is any combination of these 5 character [\x20\t\n\r\f] + // http://www.w3.org/TR/css3-selectors/#selector-syntax + reTrimSpaces = new RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + // only allow simple selectors nested in ':not()' pseudo-classes + reSimpleNot = new RegExp('^(' + + '(?!:not)' + + '(' + prefixes + + '|' + identifier + + '|\\([^()]*\\))+' + + '|\\[' + attributes + '\\]' + + ')$'), + + // split comma groups, exclude commas from + // quotes '' "" and from brackets () [] {} + reSplitGroup = new RegExp('(' + + '[^,\\\\()[\\]]+' + + '|' + skipsquare + + '|' + skipround + + '|' + skipcurly + + '|\\\\.' + + ')+', 'g'), + + // split last, right most, selector group token + reSplitToken = new RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20>+~]|\\\\.)+', 'g'), + + // for in excess whitespace removal + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = new RegExp(identifier + '|^$'), + + /*----------------------------- FEATURE TESTING ----------------------------*/ + + // detect native methods + isNative = (function() { + var s = (doc.appendChild + '').replace(/appendChild/g, ''); + return function(object, method) { + var m = object && object[method] || false; + return m && typeof m != 'string' && + s == (m + '').replace(new RegExp(method, 'g'), ''); + }; + })(), + + // NATIVE_XXXXX true if method exist and is callable + // detect if DOM methods are native in browsers + NATIVE_FOCUS = isNative(doc, 'hasFocus'), + NATIVE_QSAPI = isNative(doc, 'querySelector'), + NATIVE_GEBID = isNative(doc, 'getElementById'), + NATIVE_GEBTN = isNative(root, 'getElementsByTagName'), + NATIVE_GEBCN = isNative(root, 'getElementsByClassName'), + + // detect native getAttribute/hasAttribute methods, + // frameworks extend these to elements, but it seems + // this does not work for XML namespaced attributes, + // used to check both getAttribute/hasAttribute in IE + NATIVE_GET_ATTRIBUTE = isNative(root, 'getAttribute'), + NATIVE_HAS_ATTRIBUTE = isNative(root, 'hasAttribute'), + + // check if slice() can convert nodelist to array + // see http://yura.thinkweb2.com/cft/ + NATIVE_SLICE_PROTO = + (function() { + var isBuggy = false, id = root.id; + root.id = 'length'; + try { + isBuggy = !!slice.call(doc.childNodes, 0)[0]; + } catch(e) { } + root.id = id; + return isBuggy; + })(), + + // supports the new traversal API + NATIVE_TRAVERSAL_API = + 'nextElementSibling' in root && 'previousElementSibling' in root, + + // BUGGY_XXXXX true if method is feature tested and has known bugs + // detect buggy gEBID + BUGGY_GEBID = NATIVE_GEBID ? + (function() { + var isBuggy = true, x = 'x' + String(+new Date), + a = doc.createElementNS ? 'a' : ''; + (a = doc.createElement(a)).name = x; + root.insertBefore(a, root.firstChild); + isBuggy = !!doc.getElementById(x); + root.removeChild(a); + return isBuggy; + })() : + true, + + // detect IE gEBTN comment nodes bug + BUGGY_GEBTN = NATIVE_GEBTN ? + (function() { + var div = doc.createElement('div'); + div.appendChild(doc.createComment('')); + return !!div.getElementsByTagName('*')[0]; + })() : + true, + + // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2 + // caching class name results and not detecting when changed, + // tests are based on the jQuery selector test suite + BUGGY_GEBCN = NATIVE_GEBCN ? + (function() { + var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317'; + + // Opera tests + div.appendChild(doc.createElement('span')). + setAttribute('class', test + 'abc ' + test); + div.appendChild(doc.createElement('span')). + setAttribute('class', 'x'); + + isBuggy = !div.getElementsByClassName(test)[0]; + + // Safari test + div.lastChild.className = test; + return isBuggy || div.getElementsByClassName(test).length != 2; + })() : + true, + + // detect IE bug with dynamic attributes + BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ? + (function() { + var input = doc.createElement('input'); + input.setAttribute('value', 5); + return input.defaultValue != 5; + })() : + true, + + // detect IE bug with non-standard boolean attributes + BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ? + (function() { + var option = doc.createElement('option'); + option.setAttribute('selected', 'selected'); + return !option.hasAttribute('selected'); + })() : + true, + + // detect Safari bug with selected option elements + BUGGY_SELECTED = + (function() { + var select = doc.createElement('select'); + select.appendChild(doc.createElement('option')); + return !select.firstChild.selected; + })(), + + // initialized with the loading context + // and reset for each different context + BUGGY_QUIRKS_GEBCN, + BUGGY_QUIRKS_QSAPI, + + QUIRKS_MODE, + XML_DOCUMENT, + + // detect Opera browser + OPERA = /opera/i.test(string.call(global.opera)), + + // skip simpe selector optimizations for Opera >= 11 + OPERA_QSAPI = OPERA && parseFloat(opera.version()) >= 11, + + // check Seletor API implementations + RE_BUGGY_QSAPI = NATIVE_QSAPI ? + (function() { + var pattern = [ ], div = doc.createElement('div'), element, + + expect = function(selector, context, element, n) { + var result = false; + context.appendChild(element); + try { result = context.querySelectorAll(selector).length == n; } catch(e) { } + while (context.firstChild) { context.removeChild(context.firstChild); } + return result; + }; + + // ^= $= *= operators bugs whith empty values (Opera 10 / IE8) + element = doc.createElement('p'); + element.setAttribute('class', ''); + expect('[class^=""]', div, element, 1) && + pattern.push('[*^$]=[\\x20\\t\\n\\r\\f]*(?:""|' + "'')"); + + // :checked bug with option elements (Firefox 3.6.x) + // it wrongly includes 'selected' options elements + // HTML5 rules says selected options also match + element = doc.createElement('option'); + element.setAttribute('selected', 'selected'); + expect(':checked', div, element, 0) && + pattern.push(':checked'); + + // :enabled :disabled bugs with hidden fields (Firefox 3.5 QSA bug) + // http://www.w3.org/TR/html5/interactive-elements.html#selector-enabled + // IE8 QSA has problems too and throws error with these dynamic pseudos + element = doc.createElement('input'); + element.setAttribute('type', 'hidden'); + expect(':enabled', div, element, 0) && + pattern.push(':enabled', ':disabled'); + + // :link bugs with hyperlinks matching (Firefox/Safari) + element = doc.createElement('link'); + element.setAttribute('href', 'x'); + expect(':link', div, element, 1) || + pattern.push(':link'); + + // avoid attribute selectors for IE QSA + if (BUGGY_HAS_ATTRIBUTE) { + // IE fails in reading: + // - original values for input/textarea + // - original boolean values for controls + pattern.push('\\[[\\x20\\t\\n\\r\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)'); + } + + return pattern.length ? + new RegExp(pattern.join('|')) : + { 'test': function() { return false; } }; + + })() : + true, + + // matches class selectors + RE_CLASS = new RegExp('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')'), + + // matches simple id, tag & class selectors + RE_SIMPLE_SELECTOR = new RegExp( + !(BUGGY_GEBTN && BUGGY_GEBCN) ? !OPERA ? + '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^(?:\\*|#-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^#?-?[_a-zA-Z]{1}' + encoding + '*$'), + + /*----------------------------- LOOKUP OBJECTS -----------------------------*/ + + LINK_NODES = { 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 }, + + // boolean attributes should return attribute name instead of true/false + ATTR_BOOLEAN = { + 'checked': 1, 'disabled': 1, 'ismap': 1, + 'multiple': 1, 'readonly': 1, 'selected': 1 + }, + + // dynamic attributes that needs to be checked against original HTML value + ATTR_DEFAULT = { + 'value': 'defaultValue', + 'checked': 'defaultChecked', + 'selected': 'defaultSelected' + }, + + // attribute referencing URI data values need special treatment in IE + ATTR_URIDATA = { + 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2, + 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2 + }, + + // HTML 5 draft specifications + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + HTML_TABLE = { + // class attribute must be treated case-insensitive in HTML quirks mode + // initialized by default to Standard Mode (case-sensitive), + // set dynamically by the attribute resolver + 'class': 0, + 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, + 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, + 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, + 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, + 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, + 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, + 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 + }, + + // the following attributes must be treated case-insensitive in XHTML mode + // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity + XHTML_TABLE = { + 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1, + 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1, + 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1, + 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1 + }, + + /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/ + + // placeholder to add functionalities + Selectors = { + // as a simple example this will check + // for chars not in standard ascii table + // + // 'mySpecialSelector': { + // 'Expression': /\u0080-\uffff/, + // 'Callback': mySelectorCallback + // } + // + // 'mySelectorCallback' will be invoked + // only after passing all other standard + // checks and only if none of them worked + }, + + // attribute operators + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + // optimization expressions + Optimize = { + ID: new RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: new RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: new RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + // precompiled Regular Expressions + Patterns = { + // structural pseudo-classes and child selectors + spseudos: /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i, + // uistates + dynamic + negation pseudo-classes + dpseudos: /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i, + // element attribute matcher + attribute: new RegExp('^\\[' + attrmatcher + '\\](.*)'), + // E > F + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + // E + F + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + // E ~ F + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + // E F + ancestor: /^[\x20\t\n\r\f]+(.*)/, + // all + universal: /^\*(.*)/, + // id + id: new RegExp('^#(' + encoding + '+)(.*)'), + // tag + tagName: new RegExp('^(' + encoding + '+)(.*)'), + // class + className: new RegExp('^\\.(' + encoding + '+)(.*)') + }, + + /*------------------------------ UTIL METHODS ------------------------------*/ + + // concat elements to data + concatList = + function(data, elements) { + var i = -1, element; + if (!data.length && Array.slice) + return Array.slice(elements); + while ((element = elements[++i])) + data[data.length] = element; + return data; + }, + + // concat elements to data and callback + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + // change context specific variables + switchContext = + function(from, force) { + var div, oldDoc = doc; + // save passed context + lastContext = from; + // set new context document + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + // set document root + root = doc.documentElement; + // set host environment flags + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + + // In quirks mode css class names are case insensitive. + // In standards mode they are case sensitive. See docs: + // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = doc.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + div = doc.createElement('div'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx'); + + // GEBCN buggy in quirks mode, match count is: + // Firefox 3.0+ [xxx = 1, xXx = 1] + // Opera 10.63+ [xxx = 0, xXx = 2] + BUGGY_QUIRKS_GEBCN = + !XML_DOCUMENT && NATIVE_GEBCN && QUIRKS_MODE && + (div.getElementsByClassName('xxx').length != 2 || + div.getElementsByClassName('xXx').length != 2); + + // QSAPI buggy in quirks mode, match count is: + // At least Chrome 4+, Firefox 3.5+, Opera 10.x+, Safari 4+ [xxx = 1, xXx = 2] + // Safari 3.2 QSA doesn't work with mixedcase in quirksmode [xxx = 1, xXx = 0] + // https://bugs.webkit.org/show_bug.cgi?id=19047 + // must test the attribute selector '[class~=xxx]' + // before '.xXx' or the bug may not present itself + BUGGY_QUIRKS_QSAPI = + !XML_DOCUMENT && NATIVE_QSAPI && QUIRKS_MODE && + (div.querySelectorAll('[class~=xxx]').length != 2 || + div.querySelectorAll('.xXx').length != 2); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + /*------------------------------ DOM METHODS -------------------------------*/ + + // element by id (raw) + // @return reference or null + byIdRaw = + function(id, elements) { + var i = -1, element = null; + while ((element = elements[++i])) { + if (element.getAttribute('id') == id) { + break; + } + } + return element; + }, + + // element by id + // @return reference or null + _byId = !BUGGY_GEBID ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + // publicly exposed byId + // @return reference or null + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + // elements by tag (raw) + // @return array + byTagRaw = + function(tag, from) { + var any = tag == '*', element = from, elements = [ ], next = element.firstChild; + any || (tag = tag.toUpperCase()); + while ((element = next)) { + if (element.tagName > '@' && (any || element.tagName.toUpperCase() == tag)) { + elements[elements.length] = element; + } + if ((next = element.firstChild || element.nextSibling)) continue; + while (!next && (element = element.parentNode) && element !== from) { + next = element.nextSibling; + } + } + return elements; + }, + + // elements by tag + // @return array + _byTag = !BUGGY_GEBTN && NATIVE_SLICE_PROTO ? + function(tag, from) { + return XML_DOCUMENT || from.nodeType == 11 ? byTagRaw(tag, from) : + slice.call(from.getElementsByTagName(tag), 0); + } : + function(tag, from) { + var i = -1, j = i, data = [ ], + element, elements = from.getElementsByTagName(tag); + if (tag == '*') { + while ((element = elements[++i])) { + if (element.nodeName > '@') + data[++j] = element; + } + } else { + while ((element = elements[++i])) { + data[i] = element; + } + } + return data; + }, + + // publicly exposed byTag + // @return array + byTag = + function(tag, from) { + switchContext(from || (from = doc)); + return _byTag(tag, from); + }, + + // publicly exposed byName + // @return array + byName = + function(name, from) { + return select('[name="' + name.replace(/\\([^\\]{1})/g, '$1') + '"]', from); + }, + + // elements by class (raw) + // @return array + byClassRaw = + function(name, from) { + var i = -1, j = i, data = [ ], element, elements = _byTag('*', from), n; + name = ' ' + (QUIRKS_MODE ? name.toLowerCase() : name).replace(/\\([^\\]{1})/g, '$1') + ' '; + while ((element = elements[++i])) { + n = XML_DOCUMENT ? element.getAttribute('class') : element.className; + if (n && n.length && (' ' + (QUIRKS_MODE ? n.toLowerCase() : n). + replace(reWhiteSpace, ' ') + ' ').indexOf(name) > -1) { + data[++j] = element; + } + } + return data; + }, + + // elements by class + // @return array + _byClass = + function(name, from) { + return (BUGGY_GEBCN || BUGGY_QUIRKS_GEBCN || XML_DOCUMENT || !from.getElementsByClassName) ? + byClassRaw(name, from) : slice.call(from.getElementsByClassName(name.replace(/\\([^\\]{1})/g, '$1')), 0); + }, + + // publicly exposed byClass + // @return array + byClass = + function(name, from) { + switchContext(from || (from = doc)); + return _byClass(name, from); + }, + + // check element is descendant of container + // @return boolean + contains = 'compareDocumentPosition' in root ? + function(container, element) { + return (container.compareDocumentPosition(element) & 16) == 16; + } : 'contains' in root ? + function(container, element) { + return container !== element && container.contains(element); + } : + function(container, element) { + while ((element = element.parentNode)) { + if (element === container) return true; + } + return false; + }, + + // attribute value + // @return string + getAttribute = !BUGGY_GET_ATTRIBUTE ? + function(node, attribute) { + return node.getAttribute(attribute) || ''; + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return node[ATTR_DEFAULT[attribute]] || ''; + } + return ( + // specific URI data attributes (parameter 2 to fix IE bug) + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + // boolean attributes should return name instead of true/false + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : '' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + // attribute presence + // @return boolean + hasAttribute = !BUGGY_HAS_ATTRIBUTE ? + function(node, attribute) { + return XML_DOCUMENT ? + !!node.getAttribute(attribute) : + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + // need to get at AttributeNode first on IE + node = node.getAttributeNode(attribute); + // use both "specified" & "nodeValue" properties + return !!(node && (node.specified || node.nodeValue)); + }, + + // check node emptyness + // @return boolean + isEmpty = + function(node) { + node = node.firstChild; + while (node) { + if (node.nodeType == 3 || node.nodeName > '@') return false; + node = node.nextSibling; + } + return true; + }, + + // check if element matches the :link pseudo + // @return boolean + isLink = + function(element) { + return hasAttribute(element,'href') && LINK_NODES[element.nodeName]; + }, + + // child position by nodeType + // @return number + nthElement = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling'; + while ((element = element[succ])) { + if (element.nodeName > '@') ++count; + } + return count; + }, + + // child position by nodeName + // @return number + nthOfType = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName; + while ((element = element[succ])) { + if (element.nodeName == type) ++count; + } + return count; + }, + + /*------------------------------- DEBUGGING --------------------------------*/ + + // get/set (string/object) working modes + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + Config['USE_QSAPI'] = false; + } else if (i == 'USE_QSAPI') { + Config[i] = !!option[i] && NATIVE_QSAPI; + } + } + if (Config.SIMPLENOT) { + reValidator = new RegExp(standardValidator, 'g'); + } else { + reValidator = new RegExp(extendedValidator, 'g'); + } + return true; + }, + + // control user notifications + emit = + function(message) { + message = 'SYNTAX_ERR: ' + message + ' '; + if (Config.VERBOSITY) { + throw new SyntaxError(message); + } else { + if (global.console && global.console.log) { + global.console.log(message); + } else { + global.status += message; + } + } + }, + + Config = { + + // used to enable/disable caching of result sets + CACHING: false, + + // by default do not add missing left/right context + // to selector string shortcuts like "+div" or "ul>" + // callable Dom.shortcuts method has to be available + SHORTCUTS: false, + + // by default disable complex selectors nested in + // ':not()' pseudo-classes, as for specifications + SIMPLENOT: true, + + // HTML5 handling for the ":checked" pseudo-class + USE_HTML5: true, + + // controls enabling the Query Selector API branch + USE_QSAPI: NATIVE_QSAPI, + + // controls the engine error/warning notifications + VERBOSITY: true + + }, + + /*---------------------------- COMPILER METHODS ----------------------------*/ + + // code string reused to build compiled functions + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + + // compile a comma separated group of selector + // @mode boolean true for select, false for match + // return a compiled function + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + // ensures that source is a string + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + // for each selector in the group + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + // avoid repeating the same token + // in comma separated group (p, p) + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) { + // for select method + return new Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + } else { + // for match method + return new Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + } + }, + + // allows to cache already visited nodes + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + // compile a CSS3 string selector into ad-hoc javascript matching function + // @return string (to be compiled) + compileSelector = + function(selector, source, mode) { + + var a, b, n, k = 0, expr, match, result, status, test, type; + + while (selector) { + + k++; + + // *** Universal selector + // * match all (empty block, do not remove) + if ((match = selector.match(Patterns.universal))) { + // do nothing, handled in the compiler where + // BUGGY_GEBTN return comment nodes (ex: IE) + expr = ''; + } + + // *** ID selector + // #Foo Id case sensitive + else if ((match = selector.match(Patterns.id))) { + // document can contain conflicting elements (id/name) + // prototype selector unit need this method to recover bad HTML forms + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + // *** Type selector + // Foo Tag (case insensitive) + else if ((match = selector.match(Patterns.tagName))) { + // both tagName and nodeName properties may be upper/lower case + // depending on their creation NAMESPACE in createElementNS() + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : '.toUpperCase()' + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + // *** Class selector + // .Foo Class (case sensitive) + else if ((match = selector.match(Patterns.className))) { + // W3C CSS3 specs: element whose "class" attribute has been assigned a + // list of whitespace-separated values, see section 6.4 Class selectors + // and notes at the bottom; explicitly non-normative in this specification. + source = 'if((n=' + (XML_DOCUMENT ? + 's.getAttribute(e,"class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + // *** Attribute selector + // [attr] [attr=value] [attr="value"] [attr='value'] and !=, *=, ~=, |=, ^=, $= + // case sensitivity is treated differently depending on the document type (see map) + else if ((match = selector.match(Patterns.attribute))) { + + // xml namespaced attribute ? + expr = match[1].split(':'); + expr = expr.length == 2 ? expr[1] : expr[0] + ''; + + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + + test = false; + type = 'false'; + + // replace Operators parameter if needed + if (match[2] && match[4] && (type = Operators[match[2]])) { + // case treatment depends on document + HTML_TABLE['class'] = QUIRKS_MODE ? 1 : 0; + // replace escaped values and HTML entities + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/, '\\x$1'); + test = (XML_DOCUMENT ? XHTML_TABLE : HTML_TABLE)[expr.toLowerCase()]; + type = type.replace(/\%m/g, test ? match[4].toLowerCase() : match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + type = 'n' + match[2] + '="' + match[4] + '"'; + } + + // build expression for has/getAttribute + expr = 'n=s.' + (match[2] ? 'get' : 'has') + + 'Attribute(e,"' + match[1] + '")' + + (test ? '.toLowerCase();' : ';'); + + source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}'; + } + + // *** Adjacent sibling combinator + // E + F (F adiacent sibling of E) + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + 'var N' + k + '=e;while(e&&(e=e.previousElementSibling)){' + source + 'break;}e=N' + k + ';' : + 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + // *** General sibling combinator + // E ~ F (F relative sibling of E) + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + ('var N' + k + '=e;e=e.parentNode.firstElementChild;' + + 'while(e&&e!==N' + k + '){' + source + 'e=e.nextElementSibling;}e=N' + k + ';') : + ('var N' + k + '=e;e=e.parentNode.firstChild;' + + 'while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'); + } + + // *** Child combinator + // E > F (F children of E) + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + // *** Descendant combinator + // E F (E ancestor of F) + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + // *** Structural pseudo-classes + // :root, :empty, + // :first-child, :last-child, :only-child, + // :first-of-type, :last-of-type, :only-of-type, + // :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-of-type() + else if ((match = selector.match(Patterns.spseudos)) && match[1]) { + + switch (match[1]) { + case 'root': + // element root of the document + if (match[3]) { + source = 'if(e===h||s.contains(h,e)){' + source + '}'; + } else { + source = 'if(e===h){' + source + '}'; + } + break; + + case 'empty': + // element that has no children + source = 'if(s.isEmpty(e)){' + source + '}'; + break; + + default: + if (match[1] && match[2]) { + if (match[2] == 'n') { + source = 'if(e!==h){' + source + '}'; + break; + } else if (match[2] == 'even') { + a = 2; + b = 0; + } else if (match[2] == 'odd') { + a = 2; + b = 1; + } else { + // assumes correct "an+b" format, "b" before "a" to keep "n" values + b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0); + a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0); + if (n && n[1] == '-') a = -1; + } + + // build test expression out of structural pseudo (an+b) parameters + // see here: http://www.w3.org/TR/css3-selectors/#nth-child-pseudo + test = a > 1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ? + 'n==' + b : + (/last/i.test(match[1])) ? + a == -1 ? 'n>=' + b : 'n<=' + b : + a == -1 ? 'n<=' + b : 'n>=' + b; + + // 4 cases: 1 (nth) x 4 (child, of-type, last-child, last-of-type) + source = + 'if(e!==h){' + + 'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' + + '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' + + 'if(' + test + '){' + source + '}' + + '}'; + + } else { + // 6 cases: 3 (first, last, only) x 1 (child) x 2 (-of-type) + a = /first/i.test(match[1]) ? 'previous' : 'next'; + n = /only/i.test(match[1]) ? 'previous' : 'next'; + b = /first|last/i.test(match[1]); + + type = /-of-type/i.test(match[1]) ? '&&n.nodeName!=e.nodeName' : '&&n.nodeName<"@"'; + + source = 'if(e!==h){' + + ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source : + 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}'; + } + break; + } + + } + + // *** negation, user action and target pseudo-classes + // *** UI element states and dynamic pseudo-classes + // CSS3 :not, :checked, :enabled, :disabled, :target + // CSS3 :active, :hover, :focus + // CSS3 :link, :visited + else if ((match = selector.match(Patterns.dpseudos)) && match[1]) { + + switch (match[1].match(/^\w+/)[0]) { + // CSS3 negation pseudo-class + case 'not': + // compile nested selectors, DO NOT pass the callback parameter + // SIMPLENOT allow disabling complex selectors nested + // in ':not()' pseudo-classes, breaks some test units + expr = match[3].replace(reTrimSpaces, ''); + + if (Config.SIMPLENOT && !reSimpleNot.test(expr)) { + // see above, log error but continue execution + emit('Negation pseudo-class only accepts simple selectors "' + selector + '"'); + return ''; + } else { + if ('compatMode' in doc) { + source = 'if(!' + compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}'; + } else { + source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}'; + } + } + break; + + // CSS3 UI element states + case 'checked': + // for radio buttons checkboxes (HTML4) and options (HTML5) + source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' + + (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') + + '){' + source + '}'; + break; + case 'disabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===true){' + source + '}'; + break; + case 'enabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===false){' + source + '}'; + break; + + // CSS3 lang pseudo-class + case 'lang': + test = ''; + if (match[2]) test = match[2].substr(0, 2) + '-'; + source = 'do{(n=e.lang||"").toLowerCase();' + + 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' + + '(n&&(n=="' + match[2].toLowerCase() + + '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' + + '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);'; + break; + + // CSS3 target pseudo-class + case 'target': + n = doc.location ? doc.location.hash : ''; + if (n) { + source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}'; + } + break; + + // CSS3 dynamic pseudo-classes + case 'link': + source = 'if(s.isLink(e)&&!e.visited){' + source + '}'; + break; + case 'visited': + source = 'if(s.isLink(e)&&e.visited){' + source + '}'; + break; + + // CSS3 user action pseudo-classes IE & FF3 have native support + // these capabilities may be emulated by some event managers + case 'active': + if (XML_DOCUMENT) break; + source = 'if(e===d.activeElement){' + source + '}'; + break; + case 'hover': + if (XML_DOCUMENT) break; + source = 'if(e===d.hoverElement){' + source + '}'; + break; + case 'focus': + if (XML_DOCUMENT) break; + source = NATIVE_FOCUS ? + 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' : + 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}'; + break; + + // CSS2 selected pseudo-classes, not part of current CSS3 drafts + // the 'selected' property is only available for option elements + case 'selected': + // fix Safari selectedIndex property bug + expr = BUGGY_SELECTED ? '||(n=e.parentNode)&&n.options[n.selectedIndex]===e' : ''; + source = 'if(/^option$/i.test(e.nodeName)&&(e.selected' + expr + ')){' + source + '}'; + break; + + default: + break; + } + + } + + else { + + // this is where external extensions are + // invoked if expressions match selectors + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + // if an extension fails to parse the selector + // it must return a false boolean in "status" + if (!status) { + // log error but continue execution, don't throw real exceptions + // because blocking following processes maybe is not a good idea + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + // see above, log error but continue execution + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + // error if no matches found by the pattern scan + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + // ensure "match" is not null or empty since + // we do not throw real DOMExceptions above + selector = match && match[match.length - 1]; + } + + return source; + }, + + /*----------------------------- QUERY METHODS ------------------------------*/ + + // match element with selector + // @return boolean + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (from && from.nodeType == 1 && !contains(from, element)) { + return false; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + // compile matcher resolver if necessary + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + // select only the first element + // matching selector (document ordered) + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + // select elements matching selector + // using new Query Selector API + // or cross-browser client API + // @return array + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Missing required selector parameters'); + return [ ]; + } else if (selector === '') { + emit('Empty selector string'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid context element'); + return [ ]; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + if (!OPERA_QSAPI && RE_SIMPLE_SELECTOR.test(selector)) { + switch (selector.charAt(0)) { + case '#': + if ((element = _byId(selector.slice(1), from))) { + elements = [ element ]; + } else elements = [ ]; + break; + case '.': + elements = _byClass(selector.slice(1), from); + break; + default: + elements = _byTag(selector, from); + break; + } + } + + else if (!XML_DOCUMENT && Config.USE_QSAPI && + !(BUGGY_QUIRKS_QSAPI && RE_CLASS.test(selector)) && + !RE_BUGGY_QSAPI.test(selector)) { + try { + elements = from.querySelectorAll(selector); + } catch(e) { } + } + + if (elements) { + elements = callback ? concatCall([ ], elements, callback) : + NATIVE_SLICE_PROTO ? slice.call(elements) : concatList([ ], elements); + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + // commas separators are treated sequentially to maintain order + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (!XML_DOCUMENT && isSingleSelect) { + + if (changed) { + // get right most selector token + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + + // only last slice before :not rules + lastSlice = token.split(':not')[0]; + + // position where token was found + lastPosition = selector.length - token.length; + } + + // ID optimization RTL, to reduce number of elements to visit + if ((parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + // ID optimization LTR, to reduce selection context searches + else if ((parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if ((parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if ((parts = selector.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + for (i = 0, els = [ ]; elements.length > i; ++i) { + els = concatList(els, elements[i].getElementsByTagName('*')); + } + elements = els; + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if (NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + } + + if (!elements) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? from.childNodes : _byTag('*', from); + } + // end of prefiltering pass + + // compile selector resolver if necessary + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, '', true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + /*-------------------------------- STORAGE ---------------------------------*/ + + // compiled match functions returning booleans + matchContexts = { }, + matchResolvers = { }, + + // compiled select functions returning collections + selectContexts = { }, + selectResolvers = { }, + + // used to pass methods to compiled functions + Snapshot = { + + // element indexing methods + nthElement: nthElement, + nthOfType: nthOfType, + + // element inspection methods + getAttribute: getAttribute, + hasAttribute: hasAttribute, + + // element selection methods + byClass: _byClass, + byName: byName, + byTag: _byTag, + byId: _byId, + + // helper/check methods + contains: contains, + isEmpty: isEmpty, + isLink: isLink, + + // selection/matching + select: select, + match: match + }, + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + /*------------------------------- PUBLIC API -------------------------------*/ + + // code referenced by extensions + Dom.ACCEPT_NODE = ACCEPT_NODE; + + // log resolvers errors/warnings + Dom.emit = emit; + + // retrieve element by id attr + Dom.byId = byId; + + // retrieve elements by tag name + Dom.byTag = byTag; + + // retrieve elements by name attr + Dom.byName = byName; + + // retrieve elements by class name + Dom.byClass = byClass; + + // read the value of the attribute + // as was in the original HTML code + Dom.getAttribute = getAttribute; + + // check for the attribute presence + // as was in the original HTML code + Dom.hasAttribute = hasAttribute; + + // element match selector, return boolean true/false + Dom.match = match; + + // first element match only, return element or null + Dom.first = first; + + // elements matching selector, starting from element + Dom.select = select; + + // compile selector into ad-hoc javascript resolver + Dom.compile = compile; + + // check that two elements are ancestor/descendant + Dom.contains = contains; + + // handle selector engine configuration settings + Dom.configure = configure; + + // initialize caching for each document + Dom.setCache = function() { return; }; + + // load previously collected result set + Dom.loadResults = function() { return; }; + + // save previously collected result set + Dom.saveResults = function() { return; }; + + // handle missing context in selector strings + Dom.shortcuts = function(x) { return x; }; + + // options enabing specific engine functionality + Dom.Config = Config; + + // pass methods references to compiled resolvers + Dom.Snapshot = Snapshot; + + // operators descriptor + // for attribute operators extensions + Dom.Operators = Operators; + + // selectors descriptor + // for pseudo-class selectors extensions + Dom.Selectors = Selectors; + + // export string patterns + Dom.Tokens = Tokens; + + // add or overwrite user defined operators + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + // add selector patterns for user defined callbacks + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + /*---------------------------------- INIT ----------------------------------*/ + + // init context specific variables + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/NEW2/nwmatcher-base.js.NEW b/node_modules/jsdom/node_modules/nwmatcher/src/NEW2/nwmatcher-base.js.NEW new file mode 100644 index 0000000..9a4d97e --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/NEW2/nwmatcher-base.js.NEW @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121203 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw Error(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + hasAttribute = root.hasAttribute ? + function(node, attribute) { + return node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + node = node.getAttributeNode(attribute); + return !!(node && node.specified); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + test = 'false'; + if (match[4]) { + type = INSENSITIVE_MAP[match[1].toLowerCase()]; + match[4] = + (type ? match[4].toLowerCase() : match[4]) + .replace(/\\([0-9a-f]{2,2})/g, '\\x$1') + .replace(/(\x22|\x27)/g, '\\$1'); + } + if (match[2] && match[4] && (test = Operators[match[2]])) { + test = test.replace(/\%m/g, match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + test = 'n' + match[2] + '="' + match[4] + '"'; + } + expr = 'n=s.' + (match[2] ? 'get' : 'has') + 'Attribute(e,"' + match[1] + '")' + (type ? '.toLowerCase();' : ';'); + source = expr + 'if(' + (match[2] ? test : 'n') + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + FN = function(x) { return x; }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute, + hasAttribute: hasAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + + Dom.Operators = Operators; + Dom.Selectors = Selectors; + + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.setCache = FN; + Dom.shortcuts = FN; + Dom.loadResults = FN; + Dom.saveResults = FN; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/NEW2/nwmatcher.js.NEW b/node_modules/jsdom/node_modules/nwmatcher/src/NEW2/nwmatcher.js.NEW new file mode 100644 index 0000000..f81b5b1 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/NEW2/nwmatcher.js.NEW @@ -0,0 +1,1659 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121231 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + // in a Node.js environment, the nwmatcher functions will operate on + // the passed "browserGlobal" and will be returned in an object + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + // in a browser environment, the nwmatcher functions will operate on + // the "global" loading them and be attached to "global.NW.Dom" + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + // processing context & root element + doc = global.document, + root = doc.documentElement, + + // save utility methods references + slice = [ ].slice, + string = { }.toString, + + // persist previous parsed data + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + // accepted prefix identifiers + // (id, class & pseudo-class) + prefixes = '[#.:]?', + + // accepted attribute operators + operators = '([~*^$|!]?={1})', + + // accepted whitespace characters + whitespace = '[\\x20\\t\\n\\r\\f]*', + + // 4 combinators F E, F>E, F+E, F~E + combinators = '[\\x20]|[>+~][^>+~]', + + // an+b format params for pseudo-classes + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + // CSS quoted string values + quotedvalue = '"[^"]*"' + "|'[^']*'", + + // skip round brackets groups + skipround = '\\([^()]+\\)|\\(.*\\)', + // skip curly brackets groups + skipcurly = '\\{[^{}]+\\}|\\{.*\\}', + // skip square brackets groups + skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]', + + // skip [ ], ( ), { } brackets groups + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + // http://www.w3.org/TR/css3-syntax/#characters + // unicode/ISO 10646 characters 161 and higher + // NOTE: Safari 2.0.x crashes with escaped (\\) + // Unicode ranges in regular expressions so we + // use a negated character range class instead + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + + // CSS identifier syntax + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + // build attribute string + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + // build pseudoclass string + pseudoclass = '((?:' + + // an+b parameters or quoted string + pseudoparms + '|' + quotedvalue + '|' + + // id, class, pseudo-class selector + prefixes + '|' + encoding + '+|' + + // nested HTML attribute selector + '\\[' + attributes + '\\]|' + + // nested pseudo-class selector + '\\(.+\\)|' + whitespace + '|' + + // nested pseudos/separators + ',)+)', + + // placeholder for extensions + extensions = '.+', + + // CSS3: syntax scanner and + // one pass validation only + // using regular expression + standardValidator = + // discard start + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + // open match group + '(' + + //universal selector + '\\*' + + // id/class/tag/pseudo-class identifier + '|(?:' + prefixes + identifier + ')' + + // combinator selector + '|' + combinators + + // HTML attribute selector + '|\\[' + attributes + '\\]' + + // pseudo-classes parameters + '|\\(' + pseudoclass + '\\)' + + // dom properties selector (extension) + '|\\{' + extensions + '\\}' + + // selector group separator (comma) + '|(?:,|' + whitespace + ')' + + // close match group + ')+', + + // validator for complex selectors in ':not()' pseudo-classes + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + // validator for standard selectors as default + reValidator = new RegExp(standardValidator, 'g'), + + // whitespace is any combination of these 5 character [\x20\t\n\r\f] + // http://www.w3.org/TR/css3-selectors/#selector-syntax + reTrimSpaces = new RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + // only allow simple selectors nested in ':not()' pseudo-classes + reSimpleNot = new RegExp('^(' + + '(?!:not)' + + '(' + prefixes + + '|' + identifier + + '|\\([^()]*\\))+' + + '|\\[' + attributes + '\\]' + + ')$'), + + // split comma groups, exclude commas from + // quotes '' "" and from brackets () [] {} + reSplitGroup = new RegExp('(' + + '[^,\\\\()[\\]]+' + + '|' + skipsquare + + '|' + skipround + + '|' + skipcurly + + '|\\\\.' + + ')+', 'g'), + + // split last, right most, selector group token + reSplitToken = new RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\r\\n\\f>+~]|\\\\.)+', 'g'), + + // for in excess whitespace removal + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = new RegExp(identifier + '|^$'), + + /*----------------------------- FEATURE TESTING ----------------------------*/ + + // detect native methods + isNative = (function() { + var s = (doc.appendChild + '').replace(/appendChild/g, ''); + return function(object, method) { + var m = object && object[method] || false; + return m && typeof m != 'string' && + s == (m + '').replace(new RegExp(method, 'g'), ''); + }; + })(), + + // NATIVE_XXXXX true if method exist and is callable + // detect if DOM methods are native in browsers + NATIVE_FOCUS = isNative(doc, 'hasFocus'), + NATIVE_QSAPI = isNative(doc, 'querySelector'), + NATIVE_GEBID = isNative(doc, 'getElementById'), + NATIVE_GEBTN = isNative(root, 'getElementsByTagName'), + NATIVE_GEBCN = isNative(root, 'getElementsByClassName'), + + // detect native getAttribute/hasAttribute methods, + // frameworks extend these to elements, but it seems + // this does not work for XML namespaced attributes, + // used to check both getAttribute/hasAttribute in IE + NATIVE_GET_ATTRIBUTE = isNative(root, 'getAttribute'), + NATIVE_HAS_ATTRIBUTE = isNative(root, 'hasAttribute'), + + // check if slice() can convert nodelist to array + // see http://yura.thinkweb2.com/cft/ + NATIVE_SLICE_PROTO = + (function() { + var isBuggy = false, id = root.id; + root.id = 'length'; + try { + isBuggy = !!slice.call(doc.childNodes, 0)[0]; + } catch(e) { } + root.id = id; + return isBuggy; + })(), + + // supports the new traversal API + NATIVE_TRAVERSAL_API = + 'nextElementSibling' in root && 'previousElementSibling' in root, + + // BUGGY_XXXXX true if method is feature tested and has known bugs + // detect buggy gEBID + BUGGY_GEBID = NATIVE_GEBID ? + (function() { + var isBuggy = true, x = 'x' + String(+new Date), + a = doc.createElementNS ? 'a' : ''; + (a = doc.createElement(a)).name = x; + root.insertBefore(a, root.firstChild); + isBuggy = !!doc.getElementById(x); + root.removeChild(a); + return isBuggy; + })() : + true, + + // detect IE gEBTN comment nodes bug + BUGGY_GEBTN = NATIVE_GEBTN ? + (function() { + var div = doc.createElement('div'); + div.appendChild(doc.createComment('')); + return !!div.getElementsByTagName('*')[0]; + })() : + true, + + // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2 + // caching class name results and not detecting when changed, + // tests are based on the jQuery selector test suite + BUGGY_GEBCN = NATIVE_GEBCN ? + (function() { + var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317'; + + // Opera tests + div.appendChild(doc.createElement('span')). + setAttribute('class', test + 'abc ' + test); + div.appendChild(doc.createElement('span')). + setAttribute('class', 'x'); + + isBuggy = !div.getElementsByClassName(test)[0]; + + // Safari test + div.lastChild.className = test; + return isBuggy || div.getElementsByClassName(test).length != 2; + })() : + true, + + // detect IE bug with dynamic attributes + BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ? + (function() { + var input = doc.createElement('input'); + input.setAttribute('value', 5); + return input.defaultValue != 5; + })() : + true, + + // detect IE bug with non-standard boolean attributes + BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ? + (function() { + var option = doc.createElement('option'); + option.setAttribute('selected', 'selected'); + return !option.hasAttribute('selected'); + })() : + true, + + // detect Safari bug with selected option elements + BUGGY_SELECTED = + (function() { + var select = doc.createElement('select'); + select.appendChild(doc.createElement('option')); + return !select.firstChild.selected; + })(), + + // initialized with the loading context + // and reset for each different context + BUGGY_QUIRKS_GEBCN, + BUGGY_QUIRKS_QSAPI, + + QUIRKS_MODE, + XML_DOCUMENT, + + // detect Opera browser + OPERA = /opera/i.test(string.call(global.opera)), + + // skip simpe selector optimizations for Opera >= 11 + OPERA_QSAPI = OPERA && parseFloat(opera.version()) >= 11, + + // check Seletor API implementations + RE_BUGGY_QSAPI = NATIVE_QSAPI ? + (function() { + var pattern = [ ], div = doc.createElement('div'), element, + + expect = function(selector, context, element, n) { + var result = false; + context.appendChild(element); + try { result = context.querySelectorAll(selector).length == n; } catch(e) { } + while (context.firstChild) { context.removeChild(context.firstChild); } + return result; + }; + + // ^= $= *= operators bugs whith empty values (Opera 10 / IE8) + element = doc.createElement('p'); + element.setAttribute('class', ''); + expect('[class^=""]', div, element, 1) && + pattern.push('[*^$]=[\\x20\\t\\n\\r\\f]*(?:""|' + "'')"); + + // :checked bug with option elements (Firefox 3.6.x) + // it wrongly includes 'selected' options elements + // HTML5 rules says selected options also match + element = doc.createElement('option'); + element.setAttribute('selected', 'selected'); + expect(':checked', div, element, 0) && + pattern.push(':checked'); + + // :enabled :disabled bugs with hidden fields (Firefox 3.5) + // http://www.w3.org/TR/html5/links.html#selector-enabled + // http://www.w3.org/TR/css3-selectors/#enableddisabled + // not supported by IE8 Query Selector + element = doc.createElement('input'); + element.setAttribute('type', 'hidden'); + expect(':enabled', div, element, 0) && + pattern.push(':enabled', ':disabled'); + + // :link bugs with hyperlinks matching (Firefox/Safari) + element = doc.createElement('link'); + element.setAttribute('href', 'x'); + expect(':link', div, element, 1) || + pattern.push(':link'); + + // avoid attribute selectors for IE QSA + if (BUGGY_HAS_ATTRIBUTE) { + // IE fails in reading: + // - original values for input/textarea + // - original boolean values for controls + pattern.push('\\[[\\x20\\t\\n\\r\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)'); + } + + return pattern.length ? + new RegExp(pattern.join('|')) : + { 'test': function() { return false; } }; + + })() : + true, + + // matches class selectors + RE_CLASS = new RegExp('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')'), + + // matches simple id, tag & class selectors + RE_SIMPLE_SELECTOR = new RegExp( + !(BUGGY_GEBTN && BUGGY_GEBCN) ? !OPERA ? + '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^(?:\\*|#-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^#?-?[_a-zA-Z]{1}' + encoding + '*$'), + + /*----------------------------- LOOKUP OBJECTS -----------------------------*/ + + LINK_NODES = { 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 }, + + // boolean attributes should return attribute name instead of true/false + ATTR_BOOLEAN = { + 'checked': 1, 'disabled': 1, 'ismap': 1, + 'multiple': 1, 'readonly': 1, 'selected': 1 + }, + + // dynamic attributes that needs to be checked against original HTML value + ATTR_DEFAULT = { + 'value': 'defaultValue', + 'checked': 'defaultChecked', + 'selected': 'defaultSelected' + }, + + // attributes referencing URI data values need special treatment in IE + ATTR_URIDATA = { + 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2, + 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2 + }, + + // HTML 5 draft specifications + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + HTML_TABLE = { + // class attribute must be treated case-insensitive in HTML quirks mode + // initialized by default to Standard Mode (case-sensitive), + // set dynamically by the attribute resolver + 'class': 0, + 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, + 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, + 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, + 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, + 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, + 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, + 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 + }, + + // the following attributes must be treated case-insensitive in XHTML mode + // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity + XHTML_TABLE = { + 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1, + 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1, + 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1, + 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1 + }, + + /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/ + + // placeholder to add functionalities + Selectors = { + // as a simple example this will check + // for chars not in standard ascii table + // + // 'mySpecialSelector': { + // 'Expression': /\u0080-\uffff/, + // 'Callback': mySelectorCallback + // } + // + // 'mySelectorCallback' will be invoked + // only after passing all other standard + // checks and only if none of them worked + }, + + // attribute operators + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + // optimization expressions + Optimize = { + ID: new RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: new RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: new RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + // precompiled Regular Expressions + Patterns = { + // structural pseudo-classes and child selectors + spseudos: /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i, + // uistates + dynamic + negation pseudo-classes + dpseudos: /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i, + // element attribute matcher + attribute: new RegExp('^\\[' + attrmatcher + '\\](.*)'), + // E > F + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + // E + F + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + // E ~ F + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + // E F + ancestor: /^[\x20\t\n\r\f]+(.*)/, + // all + universal: /^\*(.*)/, + // id + id: new RegExp('^#(' + encoding + '+)(.*)'), + // tag + tagName: new RegExp('^(' + encoding + '+)(.*)'), + // class + className: new RegExp('^\\.(' + encoding + '+)(.*)') + }, + + /*------------------------------ UTIL METHODS ------------------------------*/ + + // concat elements to data + concatList = + function(data, elements) { + var i = -1, element; + if (!data.length && Array.slice) + return Array.slice(elements); + while ((element = elements[++i])) + data[data.length] = element; + return data; + }, + + // concat elements to data and callback + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + // change context specific variables + switchContext = + function(from, force) { + var div, oldDoc = doc; + // save passed context + lastContext = from; + // set new context document + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + // set document root + root = doc.documentElement; + // set host environment flags + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + + // In quirks mode css class names are case insensitive. + // In standards mode they are case sensitive. See docs: + // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = doc.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + div = doc.createElement('div'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx'); + + // GEBCN buggy in quirks mode, match count is: + // Firefox 3.0+ [xxx = 1, xXx = 1] + // Opera 10.63+ [xxx = 0, xXx = 2] + BUGGY_QUIRKS_GEBCN = + !XML_DOCUMENT && NATIVE_GEBCN && QUIRKS_MODE && + (div.getElementsByClassName('xxx').length != 2 || + div.getElementsByClassName('xXx').length != 2); + + // QSAPI buggy in quirks mode, match count is: + // At least Chrome 4+, Firefox 3.5+, Opera 10.x+, Safari 4+ [xxx = 1, xXx = 2] + // Safari 3.2 QSA doesn't work with mixedcase in quirksmode [xxx = 1, xXx = 0] + // https://bugs.webkit.org/show_bug.cgi?id=19047 + // must test the attribute selector '[class~=xxx]' + // before '.xXx' or the bug may not present itself + BUGGY_QUIRKS_QSAPI = + !XML_DOCUMENT && NATIVE_QSAPI && QUIRKS_MODE && + (div.querySelectorAll('[class~=xxx]').length != 2 || + div.querySelectorAll('.xXx').length != 2); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + /*------------------------------ DOM METHODS -------------------------------*/ + + // element by id (raw) + // @return reference or null + byIdRaw = + function(id, elements) { + var i = -1, element = null; + while ((element = elements[++i])) { + if (element.getAttribute('id') == id) { + break; + } + } + return element; + }, + + // element by id + // @return reference or null + _byId = !BUGGY_GEBID ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + // publicly exposed byId + // @return reference or null + byId = + function(id, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byId(id, from); + }, + + // elements by tag (raw) + // @return array + byTagRaw = + function(tag, from) { + var any = tag == '*', element = from, elements = [ ], next = element.firstChild; + any || (tag = tag.toUpperCase()); + while ((element = next)) { + if (element.tagName > '@' && (any || element.tagName.toUpperCase() == tag)) { + elements[elements.length] = element; + } + if ((next = element.firstChild || element.nextSibling)) continue; + while (!next && (element = element.parentNode) && element !== from) { + next = element.nextSibling; + } + } + return elements; + }, + + // elements by tag + // @return array + _byTag = !BUGGY_GEBTN && NATIVE_SLICE_PROTO ? + function(tag, from) { + return XML_DOCUMENT || from.nodeType == 11 ? byTagRaw(tag, from) : + slice.call(from.getElementsByTagName(tag), 0); + } : + function(tag, from) { + var i = -1, j = i, data = [ ], + element, elements = from.getElementsByTagName(tag); + if (tag == '*') { + while ((element = elements[++i])) { + if (element.nodeName > '@') + data[++j] = element; + } + } else { + while ((element = elements[++i])) { + data[i] = element; + } + } + return data; + }, + + // publicly exposed byTag + // @return array + byTag = + function(tag, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byTag(tag, from); + }, + + // publicly exposed byName + // @return array + byName = + function(name, from) { + return select('[name="' + name.replace(/\\([^\\]{1})/g, '$1') + '"]', from); + }, + + // elements by class (raw) + // @return array + byClassRaw = + function(name, from) { + var i = -1, j = i, data = [ ], element, elements = _byTag('*', from), n; + name = ' ' + (QUIRKS_MODE ? name.toLowerCase() : name).replace(/\\([^\\]{1})/g, '$1') + ' '; + while ((element = elements[++i])) { + n = XML_DOCUMENT ? element.getAttribute('class') : element.className; + if (n && n.length && (' ' + (QUIRKS_MODE ? n.toLowerCase() : n). + replace(reWhiteSpace, ' ') + ' ').indexOf(name) > -1) { + data[++j] = element; + } + } + return data; + }, + + // elements by class + // @return array + _byClass = + function(name, from) { + return (BUGGY_GEBCN || BUGGY_QUIRKS_GEBCN || XML_DOCUMENT || !from.getElementsByClassName) ? + byClassRaw(name, from) : slice.call(from.getElementsByClassName(name.replace(/\\([^\\]{1})/g, '$1')), 0); + }, + + // publicly exposed byClass + // @return array + byClass = + function(name, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byClass(name, from); + }, + + // check element is descendant of container + // @return boolean + contains = 'compareDocumentPosition' in root ? + function(container, element) { + return (container.compareDocumentPosition(element) & 16) == 16; + } : 'contains' in root ? + function(container, element) { + return container !== element && container.contains(element); + } : + function(container, element) { + while ((element = element.parentNode)) { + if (element === container) return true; + } + return false; + }, + + // attribute value + // @return string + getAttribute = !BUGGY_GET_ATTRIBUTE ? + function(node, attribute) { + return node.getAttribute(attribute) || ''; + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + // 'type' can only be read by using native getAttribute + attribute == 'type' ? node.getAttribute(attribute) || '' : + // specific URI data attributes (parameter 2 to fix IE bug) + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + // boolean attributes should return name instead of true/false + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + // attribute presence + // @return boolean + hasAttribute = !BUGGY_HAS_ATTRIBUTE ? + function(node, attribute) { + return XML_DOCUMENT ? + !!node.getAttribute(attribute) : + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + // read the attribute node + node = node.getAttributeNode(attribute); + return !!(node && node.specified); + }, + + // check node emptyness + // @return boolean + isEmpty = + function(node) { + node = node.firstChild; + while (node) { + if (node.nodeType == 3 || node.nodeName > '@') return false; + node = node.nextSibling; + } + return true; + }, + + // check if element matches the :link pseudo + // @return boolean + isLink = + function(element) { + return hasAttribute(element,'href') && LINK_NODES[element.nodeName]; + }, + + // child position by nodeType + // @return number + nthElement = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling'; + while ((element = element[succ])) { + if (element.nodeName > '@') ++count; + } + return count; + }, + + // child position by nodeName + // @return number + nthOfType = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName; + while ((element = element[succ])) { + if (element.nodeName == type) ++count; + } + return count; + }, + + /*------------------------------- DEBUGGING --------------------------------*/ + + // get/set (string/object) working modes + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + Config['USE_QSAPI'] = false; + } else if (i == 'USE_QSAPI') { + Config[i] = !!option[i] && NATIVE_QSAPI; + } + } + reValidator = new RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + // control user notifications + emit = + function(message) { + if (Config.VERBOSITY) { throw new Error(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + Config = { + + // used to enable/disable caching of result sets + CACHING: false, + + // by default do not add missing left/right context + // to selector string shortcuts like "+div" or "ul>" + // callable Dom.shortcuts method has to be available + SHORTCUTS: false, + + // by default disable complex selectors nested in + // ':not()' pseudo-classes, as for specifications + SIMPLENOT: true, + + // strict QSA match all non-unique IDs (false) + // speed & libs compat match unique ID (true) + UNIQUE_ID: true, + + // HTML5 handling for the ":checked" pseudo-class + USE_HTML5: true, + + // controls enabling the Query Selector API branch + USE_QSAPI: NATIVE_QSAPI, + + // controls the engine error/warning notifications + VERBOSITY: true + + }, + + /*---------------------------- COMPILER METHODS ----------------------------*/ + + // code string reused to build compiled functions + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + + // compile a comma separated group of selector + // @mode boolean true for select, false for match + // return a compiled function + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + // ensures that source is a string + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + // for each selector in the group + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + // avoid repeating the same token + // in comma separated group (p, p) + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) { + // for select method + return new Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + } else { + // for match method + return new Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + } + }, + + // allows to cache already visited nodes + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + // compile a CSS3 string selector into ad-hoc javascript matching function + // @return string (to be compiled) + compileSelector = + function(selector, source, mode) { + + var a, b, n, k = 0, expr, match, result, status, test, type; + + while (selector) { + + k++; + + // *** Universal selector + // * match all (empty block, do not remove) + if ((match = selector.match(Patterns.universal))) { + // do nothing, handled in the compiler where + // BUGGY_GEBTN return comment nodes (ex: IE) + expr = ''; + } + + // *** ID selector + // #Foo Id case sensitive + else if ((match = selector.match(Patterns.id))) { + // document can contain conflicting elements (id/name) + // prototype selector unit need this method to recover bad HTML forms + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + // *** Type selector + // Foo Tag (case insensitive) + else if ((match = selector.match(Patterns.tagName))) { + // both tagName and nodeName properties may be upper/lower case + // depending on their creation NAMESPACE in createElementNS() + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : '.toUpperCase()' + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + // *** Class selector + // .Foo Class (case sensitive) + else if ((match = selector.match(Patterns.className))) { + // W3C CSS3 specs: element whose "class" attribute has been assigned a + // list of whitespace-separated values, see section 6.4 Class selectors + // and notes at the bottom; explicitly non-normative in this specification. + source = 'if((n=' + (XML_DOCUMENT ? + 's.getAttribute(e,"class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + // *** Attribute selector + // [attr] [attr=value] [attr="value"] [attr='value'] and !=, *=, ~=, |=, ^=, $= + // case sensitivity is treated differently depending on the document type (see map) + else if ((match = selector.match(Patterns.attribute))) { + + // xml namespaced attribute ? + expr = match[1].split(':'); + expr = expr.length == 2 ? expr[1] : expr[0] + ''; + + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + + test = false; + type = 'false'; + + // replace Operators parameter if needed + if (match[2] && match[4] && (type = Operators[match[2]])) { + // case treatment depends on document + HTML_TABLE['class'] = QUIRKS_MODE ? 1 : 0; + // replace escaped values and HTML entities + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/g, '\\x$1'); + test = (XML_DOCUMENT ? XHTML_TABLE : HTML_TABLE)[expr.toLowerCase()]; + type = type.replace(/\%m/g, test ? match[4].toLowerCase() : match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + type = 'n' + match[2] + '="' + match[4] + '"'; + } + + // build expression for has/getAttribute + expr = 'n=s.' + (match[2] ? 'get' : 'has') + + 'Attribute(e,"' + match[1] + '")' + + (test ? '.toLowerCase();' : ';'); + + source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}'; + } + + // *** Adjacent sibling combinator + // E + F (F adiacent sibling of E) + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + 'var N' + k + '=e;while(e&&(e=e.previousElementSibling)){' + source + 'break;}e=N' + k + ';' : + 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + // *** General sibling combinator + // E ~ F (F relative sibling of E) + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + ('var N' + k + '=e;e=e.parentNode.firstElementChild;' + + 'while(e&&e!==N' + k + '){' + source + 'e=e.nextElementSibling;}e=N' + k + ';') : + ('var N' + k + '=e;e=e.parentNode.firstChild;' + + 'while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'); + } + + // *** Child combinator + // E > F (F children of E) + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + // *** Descendant combinator + // E F (E ancestor of F) + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + // *** Structural pseudo-classes + // :root, :empty, + // :first-child, :last-child, :only-child, + // :first-of-type, :last-of-type, :only-of-type, + // :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-of-type() + else if ((match = selector.match(Patterns.spseudos)) && match[1]) { + + switch (match[1]) { + case 'root': + // element root of the document + if (match[3]) { + source = 'if(e===h||s.contains(h,e)){' + source + '}'; + } else { + source = 'if(e===h){' + source + '}'; + } + break; + + case 'empty': + // element that has no children + source = 'if(s.isEmpty(e)){' + source + '}'; + break; + + default: + if (match[1] && match[2]) { + if (match[2] == 'n') { + source = 'if(e!==h){' + source + '}'; + break; + } else if (match[2] == 'even') { + a = 2; + b = 0; + } else if (match[2] == 'odd') { + a = 2; + b = 1; + } else { + // assumes correct "an+b" format, "b" before "a" to keep "n" values + b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0); + a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0); + if (n && n[1] == '-') a = -1; + } + + // build test expression out of structural pseudo (an+b) parameters + // see here: http://www.w3.org/TR/css3-selectors/#nth-child-pseudo + test = a > 1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ? + 'n==' + b : + (/last/i.test(match[1])) ? + a == -1 ? 'n>=' + b : 'n<=' + b : + a == -1 ? 'n<=' + b : 'n>=' + b; + + // 4 cases: 1 (nth) x 4 (child, of-type, last-child, last-of-type) + source = + 'if(e!==h){' + + 'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' + + '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' + + 'if(' + test + '){' + source + '}' + + '}'; + + } else { + // 6 cases: 3 (first, last, only) x 1 (child) x 2 (-of-type) + a = /first/i.test(match[1]) ? 'previous' : 'next'; + n = /only/i.test(match[1]) ? 'previous' : 'next'; + b = /first|last/i.test(match[1]); + + type = /-of-type/i.test(match[1]) ? '&&n.nodeName!=e.nodeName' : '&&n.nodeName<"@"'; + + source = 'if(e!==h){' + + ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source : + 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}'; + } + break; + } + + } + + // *** negation, user action and target pseudo-classes + // *** UI element states and dynamic pseudo-classes + // CSS3 :not, :checked, :enabled, :disabled, :target + // CSS3 :active, :hover, :focus + // CSS3 :link, :visited + else if ((match = selector.match(Patterns.dpseudos)) && match[1]) { + + switch (match[1].match(/^\w+/)[0]) { + // CSS3 negation pseudo-class + case 'not': + // compile nested selectors, DO NOT pass the callback parameter + // SIMPLENOT allow disabling complex selectors nested + // in ':not()' pseudo-classes, breaks some test units + expr = match[3].replace(reTrimSpaces, ''); + + if (Config.SIMPLENOT && !reSimpleNot.test(expr)) { + // see above, log error but continue execution + emit('Negation pseudo-class only accepts simple selectors "' + selector + '"'); + return ''; + } else { + if ('compatMode' in doc) { + source = 'if(!' + compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}'; + } else { + source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}'; + } + } + break; + + // CSS3 UI element states + case 'checked': + // for radio buttons checkboxes (HTML4) and options (HTML5) + source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' + + (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') + + '){' + source + '}'; + break; + case 'disabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===true){' + source + '}'; + break; + case 'enabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===false){' + source + '}'; + break; + + // CSS3 lang pseudo-class + case 'lang': + test = ''; + if (match[2]) test = match[2].substr(0, 2) + '-'; + source = 'do{(n=e.lang||"").toLowerCase();' + + 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' + + '(n&&(n=="' + match[2].toLowerCase() + + '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' + + '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);'; + break; + + // CSS3 target pseudo-class + case 'target': + n = doc.location ? doc.location.hash : ''; + if (n) { + source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}'; + } + break; + + // CSS3 dynamic pseudo-classes + case 'link': + source = 'if(s.isLink(e)&&!e.visited){' + source + '}'; + break; + case 'visited': + source = 'if(s.isLink(e)&&e.visited){' + source + '}'; + break; + + // CSS3 user action pseudo-classes IE & FF3 have native support + // these capabilities may be emulated by some event managers + case 'active': + if (XML_DOCUMENT) break; + source = 'if(e===d.activeElement){' + source + '}'; + break; + case 'hover': + if (XML_DOCUMENT) break; + source = 'if(e===d.hoverElement){' + source + '}'; + break; + case 'focus': + if (XML_DOCUMENT) break; + source = NATIVE_FOCUS ? + 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' : + 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}'; + break; + + // CSS2 selected pseudo-classes, not part of current CSS3 drafts + // the 'selected' property is only available for option elements + case 'selected': + // fix Safari selectedIndex property bug + expr = BUGGY_SELECTED ? '||(n=e.parentNode)&&n.options[n.selectedIndex]===e' : ''; + source = 'if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked' + expr + ')){' + source + '}'; + break; + + default: + break; + } + + } + + else { + + // this is where external extensions are + // invoked if expressions match selectors + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + // if an extension fails to parse the selector + // it must return a false boolean in "status" + if (!status) { + // log error but continue execution, don't throw real exceptions + // because blocking following processes maybe is not a good idea + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + // see above, log error but continue execution + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + // error if no matches found by the pattern scan + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + // ensure "match" is not null or empty since + // we do not throw real DOMExceptions above + selector = match && match[match.length - 1]; + } + + return source; + }, + + /*----------------------------- QUERY METHODS ------------------------------*/ + + // match element with selector + // @return boolean + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (from && from.nodeType == 1 && !contains(from, element)) { + return false; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + // compile matcher resolver if necessary + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + // select only the first element + // matching selector (document ordered) + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + // select elements matching selector + // using new Query Selector API + // or cross-browser client API + // @return array + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + if (!OPERA_QSAPI && RE_SIMPLE_SELECTOR.test(selector)) { + switch (selector.charAt(0)) { + case '#': + if (Config.UNIQUE_ID && (element = _byId(selector.slice(1), from))) { + elements = [ element ]; + } else elements = [ ]; + break; + case '.': + elements = _byClass(selector.slice(1), from); + break; + default: + elements = _byTag(selector, from); + break; + } + } + + else if (!XML_DOCUMENT && Config.USE_QSAPI && + !(BUGGY_QUIRKS_QSAPI && RE_CLASS.test(selector)) && + !RE_BUGGY_QSAPI.test(selector)) { + try { + elements = from.querySelectorAll(selector); + } catch(e) { } + } + + if (elements) { + elements = callback ? concatCall([ ], elements, callback) : + NATIVE_SLICE_PROTO ? slice.call(elements) : concatList([ ], elements); + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + // commas separators are treated sequentially to maintain order + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (!XML_DOCUMENT && isSingleSelect) { + + if (changed) { + // get right most selector token + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + + // only last slice before :not rules + lastSlice = token.split(':not')[0]; + + // position where token was found + lastPosition = selector.length - token.length; + } + + // ID optimization RTL, to reduce number of elements to visit + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + // ID optimization LTR, to reduce selection context searches + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if ((parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if ((parts = selector.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + for (i = 0, els = [ ]; elements.length > i; ++i) { + els = concatList(els, elements[i].getElementsByTagName('*')); + } + elements = els; + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if (NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + } + + if (!elements) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? from.childNodes : _byTag('*', from); + } + // end of prefiltering pass + + // compile selector resolver if necessary + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, '', true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + /*-------------------------------- STORAGE ---------------------------------*/ + + // empty function handler + FN = function(x) { return x; }, + + // compiled match functions returning booleans + matchContexts = { }, + matchResolvers = { }, + + // compiled select functions returning collections + selectContexts = { }, + selectResolvers = { }, + + // used to pass methods to compiled functions + Snapshot = { + + // element indexing methods + nthElement: nthElement, + nthOfType: nthOfType, + + // element inspection methods + getAttribute: getAttribute, + hasAttribute: hasAttribute, + + // element selection methods + byClass: _byClass, + byName: byName, + byTag: _byTag, + byId: _byId, + + // helper/check methods + contains: contains, + isEmpty: isEmpty, + isLink: isLink, + + // selection/matching + select: select, + match: match + }, + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + /*------------------------------- PUBLIC API -------------------------------*/ + + // code referenced by extensions + Dom.ACCEPT_NODE = ACCEPT_NODE; + + // log resolvers errors/warnings + Dom.emit = emit; + + // retrieve element by id attr + Dom.byId = byId; + + // retrieve elements by tag name + Dom.byTag = byTag; + + // retrieve elements by name attr + Dom.byName = byName; + + // retrieve elements by class name + Dom.byClass = byClass; + + // read the value of the attribute + // as was in the original HTML code + Dom.getAttribute = getAttribute; + + // check for the attribute presence + // as was in the original HTML code + Dom.hasAttribute = hasAttribute; + + // element match selector, return boolean true/false + Dom.match = match; + + // first element match only, return element or null + Dom.first = first; + + // elements matching selector, starting from element + Dom.select = select; + + // compile selector into ad-hoc javascript resolver + Dom.compile = compile; + + // check that two elements are ancestor/descendant + Dom.contains = contains; + + // handle selector engine configuration settings + Dom.configure = configure; + + // initialize caching for each document + Dom.setCache = FN; + + // load previously collected result set + Dom.loadResults = FN; + + // save previously collected result set + Dom.saveResults = FN; + + // handle missing context in selector strings + Dom.shortcuts = FN; + + // options enabing specific engine functionality + Dom.Config = Config; + + // pass methods references to compiled resolvers + Dom.Snapshot = Snapshot; + + // operators descriptor + // for attribute operators extensions + Dom.Operators = Operators; + + // selectors descriptor + // for pseudo-class selectors extensions + Dom.Selectors = Selectors; + + // export string patterns + Dom.Tokens = Tokens; + + // add or overwrite user defined operators + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + // add selector patterns for user defined callbacks + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + /*---------------------------------- INIT ----------------------------------*/ + + // init context specific variables + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD/nwmatcher-GITHUB.js b/node_modules/jsdom/node_modules/nwmatcher/src/OLD/nwmatcher-GITHUB.js new file mode 100644 index 0000000..05d2033 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD/nwmatcher-GITHUB.js @@ -0,0 +1,1648 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0beta + * Created: 20070722 + * Release: 20121122 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + // in a Node.js environment, the nwmatcher functions will operate on + // the passed "browserGlobal" and will be returned in an object + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + // in a browser environment, the nwmatcher functions will operate on + // the "global" loading them and be attached to "global.NW.Dom" + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0beta', + + Dom = exports, + + // processing context & root element + doc = global.document, + root = doc.documentElement, + + // save utility methods references + slice = [ ].slice, + string = { }.toString, + + // persist previous parsed data + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + // accepted prefix identifiers + // (id, class & pseudo-class) + prefixes = '[#.:]?', + + // accepted attribute operators + operators = '([~*^$|!]?={1})', + + // accepted whitespace characters + whitespace = '[\\x20\\t\\n\\r\\f]*', + + // 4 combinators F E, F>E, F+E, F~E + combinators = '[\\x20]|[>+~][^>+~]', + + // an+b format params for pseudo-classes + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + // CSS quoted string values + quotedvalue = '"[^"]*"' + "|'[^']*'", + + // skip group of round brackets + skipround = '\\([^()]+\\)|\\(.*\\)', + // skip group of curly brackets + skipcurly = '\\{[^{}]+\\}|\\{.*\\}', + // skip group of square brackets + skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]', + + // skip [ ], ( ), { } groups in token tails + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + // http://www.w3.org/TR/css3-syntax/#characters + // unicode/ISO 10646 characters 161 and higher + // NOTE: Safari 2.0.x crashes with escaped (\\) + // Unicode ranges in regular expressions so we + // use a negated character range class instead + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + + // CSS identifier syntax + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + // build attribute string + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + // build pseudoclass string + pseudoclass = '((?:' + + // an+b parameters or quoted string + pseudoparms + '|' + quotedvalue + '|' + + // id, class, pseudo-class selector + prefixes + '|' + encoding + '+|' + + // nested HTML attribute selector + '\\[' + attributes + '\\]|' + + // nested pseudo-class selector + '\\(.+\\)|' + whitespace + '|' + + // nested pseudos/separators + ',)+)', + + // placeholder for extensions + extensions = '.+', + + // CSS3: syntax scanner and + // one pass validation only + // using regular expression + standardValidator = + // discard start + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + // open match group + '(' + + //universal selector + '\\*' + + // id/class/tag/pseudo-class identifier + '|(?:' + prefixes + identifier + ')' + + // combinator selector + '|' + combinators + + // HTML attribute selector + '|\\[' + attributes + '\\]' + + // pseudo-classes parameters + '|\\(' + pseudoclass + '\\)' + + // dom properties selector (extension) + '|\\{' + extensions + '\\}' + + // selector group separator (comma) + '|,' + + // close match group + ')+', + + // validator for complex selectors in ':not()' pseudo-classes + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + // validator for standard selectors as default + reValidator = new RegExp(standardValidator, 'g'), + + // whitespace is any combination of these 5 character [\x20\t\n\r\f] + // http://www.w3.org/TR/css3-selectors/#selector-syntax + reTrimSpaces = new RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + // only allow simple selectors nested in ':not()' pseudo-classes + reSimpleNot = new RegExp('^(' + + '(?!:not)' + + '(' + prefixes + + '|' + identifier + + '|\\([^()]*\\))+' + + '|\\[' + attributes + '\\]' + + ')$'), + + // split comma groups, exclude commas from + // quotes '' "" and from brackets () [] {} + reSplitGroup = new RegExp('(' + + '[^,\\\\\\[\\]]+' + + '|' + skipsquare + + '|' + skipround + + '|' + skipcurly + + '|\\\\.' + + ')+', 'g'), + + // split last, right most, selector group token + reSplitToken = new RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20>+~]|\\\\.)+', 'g'), + + // for in excess whitespace removal + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = new RegExp(identifier + '|^$'), + + /*----------------------------- FEATURE TESTING ----------------------------*/ + + // detect native methods + isNative = (function() { + var s = (doc.appendChild + '').replace(/appendChild/g, ''); + return function(object, method) { + var m = object && object[method] || false; + return m && typeof m != 'string' && + s == (m + '').replace(new RegExp(method, 'g'), ''); + }; + })(), + + // NATIVE_XXXXX true if method exist and is callable + // detect if DOM methods are native in browsers + NATIVE_FOCUS = isNative(doc, 'hasFocus'), + NATIVE_QSAPI = isNative(doc, 'querySelector'), + NATIVE_GEBID = isNative(doc, 'getElementById'), + NATIVE_GEBTN = isNative(root, 'getElementsByTagName'), + NATIVE_GEBCN = isNative(root, 'getElementsByClassName'), + + // detect native getAttribute/hasAttribute methods, + // frameworks extend these to elements, but it seems + // this does not work for XML namespaced attributes, + // used to check both getAttribute/hasAttribute in IE + NATIVE_GET_ATTRIBUTE = isNative(root, 'getAttribute'), + NATIVE_HAS_ATTRIBUTE = isNative(root, 'hasAttribute'), + + // check if slice() can convert nodelist to array + // see http://yura.thinkweb2.com/cft/ + NATIVE_SLICE_PROTO = + (function() { + var isBuggy = false, id = root.id; + root.id = 'length'; + try { + isBuggy = !!slice.call(doc.childNodes, 0)[0]; + } catch(e) { } + root.id = id; + return isBuggy; + })(), + + // supports the new traversal API + NATIVE_TRAVERSAL_API = + 'nextElementSibling' in root && 'previousElementSibling' in root, + + // BUGGY_XXXXX true if method is feature tested and has known bugs + // detect buggy gEBID + BUGGY_GEBID = NATIVE_GEBID ? + (function() { + var isBuggy = true, x = 'x' + String(+new Date), + a = doc.createElementNS ? 'a' : ''; + (a = doc.createElement(a)).name = x; + root.insertBefore(a, root.firstChild); + isBuggy = !!doc.getElementById(x); + root.removeChild(a); + return isBuggy; + })() : + true, + + // detect IE gEBTN comment nodes bug + BUGGY_GEBTN = NATIVE_GEBTN ? + (function() { + var div = doc.createElement('div'); + div.appendChild(doc.createComment('')); + return !!div.getElementsByTagName('*')[0]; + })() : + true, + + // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2 + // caching class name results and not detecting when changed, + // tests are based on the jQuery selector test suite + BUGGY_GEBCN = NATIVE_GEBCN ? + (function() { + var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317'; + + // Opera tests + div.appendChild(doc.createElement('span')). + setAttribute('class', test + 'abc ' + test); + div.appendChild(doc.createElement('span')). + setAttribute('class', 'x'); + + isBuggy = !div.getElementsByClassName(test)[0]; + + // Safari test + div.lastChild.className = test; + return isBuggy || div.getElementsByClassName(test).length != 2; + })() : + true, + + // detect IE bug with dynamic attributes + BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ? + (function() { + var input = doc.createElement('input'); + input.setAttribute('value', 5); + return input.defaultValue != 5; + })() : + true, + + // detect IE bug with non-standard boolean attributes + BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ? + (function() { + var option = doc.createElement('option'); + option.setAttribute('selected', 'selected'); + return !option.hasAttribute('selected'); + })() : + true, + + // detect Safari bug with selected option elements + BUGGY_SELECTED = + (function() { + var select = doc.createElement('select'); + select.appendChild(doc.createElement('option')); + return !select.firstChild.selected; + })(), + + // initialized with the loading context + // and reset for each different context + BUGGY_QUIRKS_GEBCN, + BUGGY_QUIRKS_QSAPI, + + QUIRKS_MODE, + XML_DOCUMENT, + + // detect Opera browser + OPERA = /opera/i.test(string.call(global.opera)), + + // skip simpe selector optimizations for Opera >= 11 + OPERA_QSAPI = OPERA && parseFloat(opera.version()) >= 11, + + // check Seletor API implementations + RE_BUGGY_QSAPI = NATIVE_QSAPI ? + (function() { + var pattern = [ ], div = doc.createElement('div'), element, + + expect = function(selector, context, element, n) { + var result = false; + context.appendChild(element); + try { result = context.querySelectorAll(selector).length == n; } catch(e) { } + while (context.firstChild) { context.removeChild(context.firstChild); } + return result; + }; + + // ^= $= *= operators bugs whith empty values (Opera 10 / IE8) + element = doc.createElement('p'); + element.setAttribute('class', ''); + expect('[class^=""]', div, element, 1) && + pattern.push('[*^$]=[\\x20\\t\\n\\r\\f]*(?:""|' + "'')"); + + // :checked bug with option elements (Firefox 3.6.x) + // it wrongly includes 'selected' options elements + // HTML5 rules says selected options also match + element = doc.createElement('option'); + element.setAttribute('selected', 'selected'); + expect(':checked', div, element, 0) && + pattern.push(':checked'); + + // :enabled :disabled bugs with hidden fields (Firefox 3.5 QSA bug) + // http://www.w3.org/TR/html5/interactive-elements.html#selector-enabled + // IE8 QSA has problems too and throws error with these dynamic pseudos + element = doc.createElement('input'); + element.setAttribute('type', 'hidden'); + expect(':enabled', div, element, 1) && + pattern.push(':enabled', ':disabled'); + + // :link bugs with hyperlinks matching (Firefox/Safari) + element = doc.createElement('link'); + element.setAttribute('href', 'x'); + expect(':link', div, element, 1) || + pattern.push(':link'); + + // avoid attribute selectors for IE QSA + if (BUGGY_HAS_ATTRIBUTE) { + // IE fails in reading: + // - original values for input/textarea + // - original boolean values for controls + pattern.push('\\[[\\x20\\t\\n\\r\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)'); + } + + return pattern.length ? + new RegExp(pattern.join('|')) : + { 'test': function() { return false; } }; + + })() : + true, + + // matches class selectors + RE_CLASS = new RegExp('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')'), + + // matches simple id, tag & class selectors + RE_SIMPLE_SELECTOR = new RegExp( + !(BUGGY_GEBTN && BUGGY_GEBCN) ? !OPERA ? + '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^(?:\\*|#-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^#?-?[_a-zA-Z]{1}' + encoding + '*$'), + + /*----------------------------- LOOKUP OBJECTS -----------------------------*/ + + LINK_NODES = { 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 }, + + // boolean attributes should return attribute name instead of true/false + ATTR_BOOLEAN = { + 'checked': 1, 'disabled': 1, 'ismap': 1, + 'multiple': 1, 'readonly': 1, 'selected': 1 + }, + + // dynamic attributes that needs to be checked against original HTML value + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + // attribute referencing URI data values need special treatment in IE + ATTR_URIDATA = { + 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2, + 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2 + }, + + // HTML 5 draft specifications + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + HTML_TABLE = { + // class attribute must be treated case-insensitive in HTML quirks mode + // initialized by default to Standard Mode (case-sensitive), + // set dynamically by the attribute resolver + 'class': 0, + 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, + 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, + 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, + 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, + 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, + 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, + 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 + }, + + // the following attributes must be treated case-insensitive in XHTML mode + // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity + XHTML_TABLE = { + 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1, + 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1, + 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1, + 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1 + }, + + /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/ + + // placeholder to add functionalities + Selectors = { + // as a simple example this will check + // for chars not in standard ascii table + // + // 'mySpecialSelector': { + // 'Expression': /\u0080-\uffff/, + // 'Callback': mySelectorCallback + // } + // + // 'mySelectorCallback' will be invoked + // only after passing all other standard + // checks and only if none of them worked + }, + + // attribute operators + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + // optimization expressions + Optimize = { + ID: new RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: new RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: new RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + // precompiled Regular Expressions + Patterns = { + // structural pseudo-classes and child selectors + spseudos: /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\((even|odd|(?:[+-]{0,1}\d*n)?[+-]{0,1}\d*)\))?(.*)/, + // uistates + dynamic + negation pseudo-classes + dpseudos: /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/, + // element attribute matcher + attribute: new RegExp('^\\[' + attrmatcher + '\\](.*)'), + // E > F + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + // E + F + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + // E ~ F + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + // E F + ancestor: /^[\x20\t\n\r\f]+(.*)/, + // all + universal: /^\*(.*)/, + // id + id: new RegExp('^#(' + encoding + '+)(.*)'), + // tag + tagName: new RegExp('^(' + encoding + '+)(.*)'), + // class + className: new RegExp('^\\.(' + encoding + '+)(.*)') + }, + + /*------------------------------ UTIL METHODS ------------------------------*/ + + // concat elements to data + concatList = + function(data, elements) { + var i = -1, element; + if (!data.length && Array.slice) + return Array.slice(elements); + while ((element = elements[++i])) + data[data.length] = element; + return data; + }, + + // concat elements to data and callback + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + // change context specific variables + switchContext = + function(from, force) { + var div, oldDoc = doc; + // save passed context + lastContext = from; + // set new context document + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + // set document root + root = doc.documentElement; + // set host environment flags + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + + // In quirks mode css class names are case insensitive. + // In standards mode they are case sensitive. See docs: + // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = doc.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + div = doc.createElement('div'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx'); + + // GEBCN buggy in quirks mode, match count is: + // Firefox 3.0+ [xxx = 1, xXx = 1] + // Opera 10.63+ [xxx = 0, xXx = 2] + BUGGY_QUIRKS_GEBCN = + !XML_DOCUMENT && NATIVE_GEBCN && QUIRKS_MODE && + (div.getElementsByClassName('xxx').length != 2 || + div.getElementsByClassName('xXx').length != 2); + + // QSAPI buggy in quirks mode, match count is: + // At least Chrome 4+, Firefox 3.5+, Opera 10.x+, Safari 4+ [xxx = 1, xXx = 2] + // Safari 3.2 QSA doesn't work with mixedcase in quirksmode [xxx = 1, xXx = 0] + // https://bugs.webkit.org/show_bug.cgi?id=19047 + // must test the attribute selector '[class~=xxx]' + // before '.xXx' or the bug may not present itself + BUGGY_QUIRKS_QSAPI = + !XML_DOCUMENT && NATIVE_QSAPI && QUIRKS_MODE && + (div.querySelectorAll('[class~=xxx]').length != 2 || + div.querySelectorAll('.xXx').length != 2); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + /*------------------------------ DOM METHODS -------------------------------*/ + + // element by id (raw) + // @return reference or null + byIdRaw = + function(id, elements) { + var i = -1, element = null; + while ((element = elements[++i])) { + if (element.getAttribute('id') == id) { + break; + } + } + return element; + }, + + // element by id + // @return reference or null + _byId = !BUGGY_GEBID ? + function(id, from) { + id = id.replace(/\\/g, ''); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\/g, ''); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + // publicly exposed byId + // @return reference or null + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + // elements by tag (raw) + // @return array + byTagRaw = + function(tag, from) { + var any = tag == '*', element = from, elements = [ ], next = element.firstChild; + any || (tag = tag.toUpperCase()); + while ((element = next)) { + if (element.tagName > '@' && (any || element.tagName.toUpperCase() == tag)) { + elements[elements.length] = element; + } + if ((next = element.firstChild || element.nextSibling)) continue; + while (!next && (element = element.parentNode) && element !== from) { + next = element.nextSibling; + } + } + return elements; + }, + + // elements by tag + // @return array + _byTag = !BUGGY_GEBTN && NATIVE_SLICE_PROTO ? + function(tag, from) { + return XML_DOCUMENT || from.nodeType == 11 ? byTagRaw(tag, from) : + slice.call(from.getElementsByTagName(tag), 0); + } : + function(tag, from) { + var i = -1, j = i, data = [ ], + element, elements = from.getElementsByTagName(tag); + if (tag == '*') { + while ((element = elements[++i])) { + if (element.nodeName > '@') + data[++j] = element; + } + } else { + while ((element = elements[++i])) { + data[i] = element; + } + } + return data; + }, + + // publicly exposed byTag + // @return array + byTag = + function(tag, from) { + switchContext(from || (from = doc)); + return _byTag(tag, from); + }, + + // publicly exposed byName + // @return array + byName = + function(name, from) { + return select('[name="' + name.replace(/\\/g, '') + '"]', from); + }, + + // elements by class (raw) + // @return array + byClassRaw = + function(name, from) { + var i = -1, j = i, data = [ ], element, elements = _byTag('*', from), n; + name = ' ' + (QUIRKS_MODE ? name.toLowerCase() : name).replace(/\\/g, '') + ' '; + while ((element = elements[++i])) { + n = XML_DOCUMENT ? element.getAttribute('class') : element.className; + if (n && n.length && (' ' + (QUIRKS_MODE ? n.toLowerCase() : n). + replace(reWhiteSpace, ' ') + ' ').indexOf(name) > -1) { + data[++j] = element; + } + } + return data; + }, + + // elements by class + // @return array + _byClass = + function(name, from) { + return (BUGGY_GEBCN || BUGGY_QUIRKS_GEBCN || XML_DOCUMENT || !from.getElementsByClassName) ? + byClassRaw(name, from) : slice.call(from.getElementsByClassName(name.replace(/\\/g, '')), 0); + }, + + // publicly exposed byClass + // @return array + byClass = + function(name, from) { + switchContext(from || (from = doc)); + return _byClass(name, from); + }, + + // check element is descendant of container + // @return boolean + contains = 'compareDocumentPosition' in root ? + function(container, element) { + return (container.compareDocumentPosition(element) & 16) == 16; + } : 'contains' in root ? + function(container, element) { + return container !== element && container.contains(element); + } : + function(container, element) { + while ((element = element.parentNode)) { + if (element === container) return true; + } + return false; + }, + + // attribute value + // @return string + getAttribute = !BUGGY_GET_ATTRIBUTE ? + function(node, attribute) { + return node.getAttribute(attribute) || ''; + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return node[ATTR_DEFAULT[attribute]] || ''; + } + return ( + // specific URI data attributes (parameter 2 to fix IE bug) + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + // boolean attributes should return name instead of true/false + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : '' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + // attribute presence + // @return boolean + hasAttribute = !BUGGY_HAS_ATTRIBUTE ? + function(node, attribute) { + return XML_DOCUMENT ? + !!node.getAttribute(attribute) : + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + // need to get at AttributeNode first on IE + node = node.getAttributeNode(attribute); + // use both "specified" & "nodeValue" properties + return !!(node && (node.specified || node.nodeValue)); + }, + + // check node emptyness + // @return boolean + isEmpty = + function(node) { + node = node.firstChild; + while (node) { + if (node.nodeType == 3 || node.nodeName > '@') return false; + node = node.nextSibling; + } + return true; + }, + + // check if element matches the :link pseudo + // @return boolean + isLink = + function(element) { + return hasAttribute(element,'href') && LINK_NODES[element.nodeName]; + }, + + // child position by nodeType + // @return number + nthElement = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling'; + while ((element = element[succ])) { + if (element.nodeName > '@') ++count; + } + return count; + }, + + // child position by nodeName + // @return number + nthOfType = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName; + while ((element = element[succ])) { + if (element.nodeName == type) ++count; + } + return count; + }, + + /*------------------------------- DEBUGGING --------------------------------*/ + + // get/set (string/object) working modes + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + Config['USE_QSAPI'] = false; + reValidator = new RegExp(extendedValidator, 'g'); + } else if (i == 'USE_QSAPI') { + Config[i] = !!option[i] && NATIVE_QSAPI; + reValidator = new RegExp(standardValidator, 'g'); + } + } + return true; + }, + + // control user notifications + emit = + function(message) { + message = 'SYNTAX_ERR: ' + message + ' '; + if (Config.VERBOSITY) { + throw new SyntaxError(message); + } else { + if (global.console && global.console.log) { + global.console.log(message); + } else { + global.status += message; + } + } + }, + + Config = { + + // used to enable/disable caching of result sets + CACHING: false, + + // by default do not add missing left/right context + // to selector string shortcuts like "+div" or "ul>" + // callable Dom.shortcuts method has to be available + SHORTCUTS: false, + + // by default disable complex selectors nested in + // ':not()' pseudo-classes, as for specifications + SIMPLENOT: true, + + // HTML5 handling for the ":checked" pseudo-class + USE_HTML5: false, + + // controls enabling the Query Selector API branch + USE_QSAPI: NATIVE_QSAPI, + + // controls the engine error/warning notifications + VERBOSITY: true + + }, + + /*---------------------------- COMPILER METHODS ----------------------------*/ + + // code string reused to build compiled functions + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break;else continue main;', + + // compile a comma separated group of selector + // @mode boolean true for select, false for match + // return a compiled function + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + // ensures that source is a string + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + // for each selector in the group + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + // avoid repeating the same token + // in comma separated group (p, p) + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) { + // for select method + return new Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + } else { + // for match method + return new Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + } + }, + + // allows to cache already visited nodes + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + // compile a CSS3 string selector into ad-hoc javascript matching function + // @return string (to be compiled) + compileSelector = + function(selector, source, mode) { + + var a, b, n, k = 0, expr, match, result, status, test, type; + + while (selector) { + + k++; + + // *** Universal selector + // * match all (empty block, do not remove) + if ((match = selector.match(Patterns.universal))) { + // do nothing, handled in the compiler where + // BUGGY_GEBTN return comment nodes (ex: IE) + expr = ''; + } + + // *** ID selector + // #Foo Id case sensitive + else if ((match = selector.match(Patterns.id))) { + // document can contain conflicting elements (id/name) + // prototype selector unit need this method to recover bad HTML forms + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + // *** Type selector + // Foo Tag (case insensitive) + else if ((match = selector.match(Patterns.tagName))) { + // both tagName and nodeName properties may be upper/lower case + // depending on their creation NAMESPACE in createElementNS() + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : '.toUpperCase()' + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + // *** Class selector + // .Foo Class (case sensitive) + else if ((match = selector.match(Patterns.className))) { + // W3C CSS3 specs: element whose "class" attribute has been assigned a + // list of whitespace-separated values, see section 6.4 Class selectors + // and notes at the bottom; explicitly non-normative in this specification. + source = 'if((n=' + (XML_DOCUMENT ? + 's.getAttribute(e,"class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + // *** Attribute selector + // [attr] [attr=value] [attr="value"] [attr='value'] and !=, *=, ~=, |=, ^=, $= + // case sensitivity is treated differently depending on the document type (see map) + else if ((match = selector.match(Patterns.attribute))) { + + // xml namespaced attribute ? + expr = match[1].split(':'); + expr = expr.length == 2 ? expr[1] : expr[0] + ''; + + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + + test = false; + type = 'false'; + + // replace Operators parameter if needed + if (match[2] && match[4] && (type = Operators[match[2]])) { + // case treatment depends on document + HTML_TABLE['class'] = QUIRKS_MODE ? 1 : 0; + // replace escaped values and HTML entities + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/, '\\x$1'); + test = (XML_DOCUMENT ? XHTML_TABLE : HTML_TABLE)[expr.toLowerCase()]; + type = type.replace(/\%m/g, test ? match[4].toLowerCase() : match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + type = 'n' + match[2] + '="' + match[4] + '"'; + } + + // build expression for has/getAttribute + expr = 'n=s.' + (match[2] ? 'get' : 'has') + + 'Attribute(e,"' + match[1] + '")' + + (test ? '.toLowerCase();' : ';'); + + source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}'; + } + + // *** Adjacent sibling combinator + // E + F (F adiacent sibling of E) + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + 'var N' + k + '=e;while(e&&(e=e.previousElementSibling)){' + source + 'break;}e=N' + k + ';' : + 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + // *** General sibling combinator + // E ~ F (F relative sibling of E) + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + ('var N' + k + '=e;e=e.parentNode.firstElementChild;' + + 'while(e&&e!==N' + k + '){' + source + 'e=e.nextElementSibling;}e=N' + k + ';') : + ('var N' + k + '=e;e=e.parentNode.firstChild;' + + 'while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'); + } + + // *** Child combinator + // E > F (F children of E) + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + // *** Descendant combinator + // E F (E ancestor of F) + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + // *** Structural pseudo-classes + // :root, :empty, + // :first-child, :last-child, :only-child, + // :first-of-type, :last-of-type, :only-of-type, + // :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-of-type() + else if ((match = selector.match(Patterns.spseudos)) && match[1]) { + + switch (match[1]) { + case 'root': + // element root of the document + if (match[3]) { + source = 'if(e===h||s.contains(h,e)){' + source + '}'; + } else { + source = 'if(e===h){' + source + '}'; + } + break; + + case 'empty': + // element that has no children + source = 'if(s.isEmpty(e)){' + source + '}'; + break; + + default: + if (match[1] && match[2]) { + if (match[2] == 'n') { + source = 'if(e!==h){' + source + '}'; + break; + } else if (match[2] == 'even') { + a = 2; + b = 0; + } else if (match[2] == 'odd') { + a = 2; + b = 1; + } else { + // assumes correct "an+b" format, "b" before "a" to keep "n" values + b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0); + a = ((n = match[2].match(/(-?\d*)n/)) ? parseInt(n[1], 10) : 0); + if (n && n[1] == '-') a = -1; + } + + // build test expression out of structural pseudo (an+b) parameters + // see here: http://www.w3.org/TR/css3-selectors/#nth-child-pseudo + test = a > 1 ? + (/last/.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ? + (/last/.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ? + 'n==' + b : + (/last/.test(match[1])) ? + a == -1 ? 'n>=' + b : 'n<=' + b : + a == -1 ? 'n<=' + b : 'n>=' + b; + + // 4 cases: 1 (nth) x 4 (child, of-type, last-child, last-of-type) + source = + 'if(e!==h){' + + 'n=s[' + (/-of-type/.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' + + '(e,' + (/last/.test(match[1]) ? 'true' : 'false') + ');' + + 'if(' + test + '){' + source + '}' + + '}'; + + } else { + // 6 cases: 3 (first, last, only) x 1 (child) x 2 (-of-type) + a = /first/.test(match[1]) ? 'previous' : 'next'; + n = /only/.test(match[1]) ? 'previous' : 'next'; + b = /first|last/.test(match[1]); + + type = /of-type/.test(match[1]) ? '&&n.nodeName!=e.nodeName' : '&&n.nodeName<"@"'; + + source = 'if(e!==h){' + + ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source : + 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}'; + } + break; + } + + } + + // *** negation, user action and target pseudo-classes + // *** UI element states and dynamic pseudo-classes + // CSS3 :not, :checked, :enabled, :disabled, :target + // CSS3 :active, :hover, :focus + // CSS3 :link, :visited + else if ((match = selector.match(Patterns.dpseudos)) && match[1]) { + + switch (match[1].match(/^\w+/)[0]) { + // CSS3 negation pseudo-class + case 'not': + // compile nested selectors, DO NOT pass the callback parameter + // SIMPLENOT allow disabling complex selectors nested + // in ':not()' pseudo-classes, breaks some test units + expr = match[3].replace(reTrimSpaces, ''); + + if (Config.SIMPLENOT && !reSimpleNot.test(expr)) { + // see above, log error but continue execution + emit('Negation pseudo-class only accepts simple selectors "' + selector + '"'); + return ''; + } else { + if ('compatMode' in doc) { + source = 'if(!' + compile([expr], '', false) + '(e,s,r,d,h,g)){' + source + '}'; + } else { + source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}'; + } + } + break; + + // CSS3 UI element states + case 'checked': + // for radio buttons checkboxes (HTML4) and options (HTML5) + test = 'if((typeof e.form!="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)'; + source = (Config.USE_HTML5 ? test + '||(/^option$/i.test(e.nodeName)&&e.selected)' : test) + '){' + source + '}'; + break; + case 'disabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!="undefined"&&!(/^hidden$/i).test(e.type))||s.isLink(e))&&e.disabled){' + source + '}'; + break; + case 'enabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!="undefined"&&!(/^hidden$/i).test(e.type))||s.isLink(e))&&!e.disabled){' + source + '}'; + break; + + // CSS3 lang pseudo-class + case 'lang': + test = ''; + if (match[2]) test = match[2].substr(0, 2) + '-'; + source = 'do{(n=e.lang||"").toLowerCase();' + + 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' + + '(n&&(n=="' + match[2].toLowerCase() + + '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' + + '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);'; + break; + + // CSS3 target pseudo-class + case 'target': + n = doc.location ? doc.location.hash : ''; + if (n) { + source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}'; + } + break; + + // CSS3 dynamic pseudo-classes + case 'link': + source = 'if(s.isLink(e)&&!e.visited){' + source + '}'; + break; + case 'visited': + source = 'if(s.isLink(e)&&e.visited){' + source + '}'; + break; + + // CSS3 user action pseudo-classes IE & FF3 have native support + // these capabilities may be emulated by some event managers + case 'active': + if (XML_DOCUMENT) break; + source = 'if(e===d.activeElement){' + source + '}'; + break; + case 'hover': + if (XML_DOCUMENT) break; + source = 'if(e===d.hoverElement){' + source + '}'; + break; + case 'focus': + if (XML_DOCUMENT) break; + source = NATIVE_FOCUS ? + 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href)){' + source + '}' : + 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}'; + break; + + // CSS2 selected pseudo-classes, not part of current CSS3 drafts + // the 'selected' property is only available for option elements + case 'selected': + // fix Safari selectedIndex property bug + expr = BUGGY_SELECTED ? '||(n=e.parentNode)&&n.options[n.selectedIndex]===e' : ''; + source = 'if(/^option$/i.test(e.nodeName)&&(e.selected' + expr + ')){' + source + '}'; + break; + + default: + break; + } + + } + + else { + + // this is where external extensions are + // invoked if expressions match selectors + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + // if an extension fails to parse the selector + // it must return a false boolean in "status" + if (!status) { + // log error but continue execution, don't throw real exceptions + // because blocking following processes maybe is not a good idea + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + // see above, log error but continue execution + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + // error if no matches found by the pattern scan + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + // ensure "match" is not null or empty since + // we do not throw real DOMExceptions above + selector = match && match[match.length - 1]; + } + + return source; + }, + + /*----------------------------- QUERY METHODS ------------------------------*/ + + // match element with selector + // @return boolean + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (from && from.nodeType == 1 && !contains(from, element)) { + return false; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + // compile matcher resolver if necessary + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + // select only the first element + // matching selector (document ordered) + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + // select elements matching selector + // using new Query Selector API + // or cross-browser client API + // @return array + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Missing required selector parameters'); + return [ ]; + } else if (selector === '') { + emit('Empty selector string'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid context element'); + return [ ]; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + if (!OPERA_QSAPI && RE_SIMPLE_SELECTOR.test(selector)) { + switch (selector.charAt(0)) { + case '#': + if ((element = _byId(selector.slice(1), from))) { + elements = [ element ]; + } else elements = [ ]; + break; + case '.': + elements = _byClass(selector.slice(1), from); + break; + default: + elements = _byTag(selector, from); + break; + } + } + + else if (!XML_DOCUMENT && Config.USE_QSAPI && + !(BUGGY_QUIRKS_QSAPI && RE_CLASS.test(selector)) && + !RE_BUGGY_QSAPI.test(selector)) { + try { + elements = from.querySelectorAll(selector); + } catch(e) { } + } + + if (elements) { + elements = callback ? concatCall([ ], elements, callback) : + NATIVE_SLICE_PROTO ? slice.call(elements) : concatList([ ], elements); + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + // commas separators are treated sequentially to maintain order + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (!XML_DOCUMENT && isSingleSelect) { + + if (changed) { + // get right most selector token + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + + // only last slice before :not rules + lastSlice = token.split(':not')[0]; + + // position where token was found + lastPosition = selector.length - token.length; + } + + // ID optimization RTL, to reduce number of elements to visit + if ((parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + // ID optimization LTR, to reduce selection context searches + else if ((parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } + if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + selector = selector.replace('#' + token, '*'); + lastPosition -= token.length + 1; + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if ((parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if ((parts = selector.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + for (i = 0, els = [ ]; elements.length > i; ++i) { + els = concatList(els, elements[i].getElementsByTagName('*')); + } + elements = els; + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if (NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + } + + if (!elements) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? from.childNodes : _byTag('*', from); + } + // end of prefiltering pass + + // compile selector resolver if necessary + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, '', true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + /*-------------------------------- STORAGE ---------------------------------*/ + + // compiled match functions returning booleans + matchContexts = { }, + matchResolvers = { }, + + // compiled select functions returning collections + selectContexts = { }, + selectResolvers = { }, + + // used to pass methods to compiled functions + Snapshot = { + + // element indexing methods + nthElement: nthElement, + nthOfType: nthOfType, + + // element inspection methods + getAttribute: getAttribute, + hasAttribute: hasAttribute, + + // element selection methods + byClass: _byClass, + byName: byName, + byTag: _byTag, + byId: _byId, + + // helper/check methods + contains: contains, + isEmpty: isEmpty, + isLink: isLink, + + // selection/matching + select: select, + match: match + }, + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + /*------------------------------- PUBLIC API -------------------------------*/ + + // code referenced by extensions + Dom.ACCEPT_NODE = ACCEPT_NODE; + + // log resolvers errors/warnings + Dom.emit = emit; + + // retrieve element by id attr + Dom.byId = byId; + + // retrieve elements by tag name + Dom.byTag = byTag; + + // retrieve elements by name attr + Dom.byName = byName; + + // retrieve elements by class name + Dom.byClass = byClass; + + // read the value of the attribute + // as was in the original HTML code + Dom.getAttribute = getAttribute; + + // check for the attribute presence + // as was in the original HTML code + Dom.hasAttribute = hasAttribute; + + // element match selector, return boolean true/false + Dom.match = match; + + // first element match only, return element or null + Dom.first = first; + + // elements matching selector, starting from element + Dom.select = select; + + // compile selector into ad-hoc javascript resolver + Dom.compile = compile; + + // check that two elements are ancestor/descendant + Dom.contains = contains; + + // handle selector engine configuration settings + Dom.configure = configure; + + // initialize caching for each document + Dom.setCache = function() { return; }; + + // load previously collected result set + Dom.loadResults = function() { return; }; + + // save previously collected result set + Dom.saveResults = function() { return; }; + + // handle missing context in selector strings + Dom.shortcuts = function(x) { return x; }; + + // options enabing specific engine functionality + Dom.Config = Config; + + // pass methods references to compiled resolvers + Dom.Snapshot = Snapshot; + + // operators descriptor + // for attribute operators extensions + Dom.Operators = Operators; + + // selectors descriptor + // for pseudo-class selectors extensions + Dom.Selectors = Selectors; + + // export string patterns + Dom.Tokens = Tokens; + + // add or overwrite user defined operators + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + // add selector patterns for user defined callbacks + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + /*---------------------------------- INIT ----------------------------------*/ + + // init context specific variables + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD/nwmatcher-base-GITHUB.js b/node_modules/jsdom/node_modules/nwmatcher/src/OLD/nwmatcher-base-GITHUB.js new file mode 100644 index 0000000..4f88a95 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD/nwmatcher-base-GITHUB.js @@ -0,0 +1,669 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0beta + * Created: 20070722 + * Release: 20121122 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0beta', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|,' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\\\[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + REFLECTED = { 'value': 1, 'checked': 1, 'selected': 1 }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + USE_HTML5: false, + USE_QSAPI: false, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + Config['USE_QSAPI'] = false; + reValidator = RegExp(extendedValidator, 'g'); + } else if (i == 'USE_QSAPI') { + reValidator = RegExp(standardValidator, 'g'); + } + } + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + message = 'SYNTAX_ERR: ' + message + ' '; + if (Config.VERBOSITY) { + throw SyntaxError(message); + } else { + if (global.console && global.console.log) { + global.console.log(message); + } else { + global.status += message; + } + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\/g, ''); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\/g, ''); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttr = + function(node, attribute) { + return ( + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ((node = node.attributes[attribute]) && node.value) || ''); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttr(e,"id")' : + '(e.submit?s.getAttr(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + name = match[1].toLowerCase(); + if (match[2] && match[4] && (type = Operators[match[2]])) { + test = name in INSENSITIVE_MAP; + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/, '\\x$1'); + type = type.replace(/\%m/g, test ? match[4].toLowerCase() : match[4]); + expr = 'n=s.getAttr(e,"' + name + '")' + (test ? '.toLowerCase()' : '') + ';'; + } else if (!match[2]) { + if (REFLECTED[name]) { + test = 'default' + name.charAt(0).toUpperCase() + name.slice(1); + expr = 'n=e["' + test + '"];'; + type = 'n'; + } else { + expr = 'n=e.attributes["' + name + '"];'; + type = IE_LT_9 ? 'n&&n.specified' : 'n'; + } + } else if (match[2] == '!=' || match[2] == '=') { + expr = 'n=e.attributes["' + name + '"];'; + type = 'n&&n.value' + match[2] + '="' + match[4] + '"'; + } else { + expr = ''; + type = 'false'; + } + source = expr + 'if(' + type + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Missing required selector parameters'); + return [ ]; + } else if (selector === '') { + emit('Empty selector string'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if ((parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if ((parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } + if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + selector = selector.replace('#' + token, '*'); + lastPosition -= token.length + 1; + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\/g, ''))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttr: getAttr + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + Dom.Operators = Operators; + Dom.Selectors = Selectors; + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.setCache = function() { return; }; + Dom.loadResults = function() { return; }; + Dom.saveResults = function() { return; }; + + Dom.shortcuts = function(x) { return x; }; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.GITHUB b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.GITHUB new file mode 100644 index 0000000..29c6eea --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.GITHUB @@ -0,0 +1,673 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121203 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + REFLECTED = { 'value': 1, 'checked': 1, 'selected': 1 }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw SyntaxError(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + name = match[1].toLowerCase(); + if (match[2] && match[4] && (type = Operators[match[2]])) { + test = name in INSENSITIVE_MAP; + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/, '\\x$1'); + type = type.replace(/\%m/g, match[4].toLowerCase()); + expr = 'n=s.getAttribute(e,"' + name + '").toLowerCase();'; + } else if (!match[2]) { + if (REFLECTED[name]) { + test = 'default' + name.charAt(0).toUpperCase() + name.slice(1); + expr = 'n=e["' + test + '"];'; + type = 'n'; + } else { + expr = 'n=e.attributes["' + name + '"];'; + type = IE_LT_9 ? 'n&&n.specified' : 'n'; + } + } else if (match[2] == '!=' || match[2] == '=') { + expr = 'n=e.attributes["' + name + '"];'; + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + type = 'n&&n.value' + match[2] + '="' + match[4] + '"'; + } else { + expr = ''; + type = 'false'; + } + source = expr + 'if(' + type + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + Dom.Operators = Operators; + Dom.Selectors = Selectors; + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.setCache = function() { return; }; + Dom.loadResults = function() { return; }; + Dom.saveResults = function() { return; }; + + Dom.shortcuts = function(x) { return x; }; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW new file mode 100644 index 0000000..088b80c --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW @@ -0,0 +1,697 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121203 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw SyntaxError(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + hasAttribute = root.hasAttribute ? + function(node, attribute) { + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + expr = ''; + type = 'false'; + name = match[1].toLowerCase(); + if (match[2] && match[4] && (type = Operators[match[2]])) { + test = match[4].replace(/(\x22|\x27)/g, '\\$1'); + test = test.replace(/\\([0-9a-f]{2,2})/g, '\\x$1'); + expr = 'n=s.getAttribute(e,"' + name + '").toLowerCase();'; + type = type.replace(/\%m/g, test.toLowerCase()); + } else if (!match[2]) { + expr = 'n=s.hasAttribute(e,"' + name + '");'; + type = 'n'; +/* + expr = 'n=e.' + (IE_LT_9 ? + 'getAttributeNode("' + name + '");' : + 'hasAttribute("' + name + '");'); + type = IE_LT_9 ? ATTR_DEFAULT[name] ? + '!!e.' + ATTR_DEFAULT[name] : + 'n&&(n.specified||n.nodeValue)' : 'n'; +*/ + } else if (match[2] == '!=' || match[2] == '=') { + test = match[4].replace(/(\x22|\x27)/g, '\\$1'); + expr = 'n=e.getAttribute("' + name + '");'; + type = 'n' + match[2] + '="' + test + '"'; + } + source = expr + 'if(' + type + '){' + source + '}'; +//if (name == 'multiple') alert(source); + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + FN = function(x) { return x; }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute, + hasAttribute: hasAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + + Dom.Operators = Operators; + Dom.Selectors = Selectors; + + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.loadResults = FN; + Dom.saveResults = FN; + Dom.setCache = FN; + + Dom.shortcuts = FN; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW2 b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW2 new file mode 100644 index 0000000..7ad69c0 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW2 @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121203 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw SyntaxError(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + hasAttribute = root.hasAttribute ? + function(node, attribute) { + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + expr = ''; + type = 'false'; + name = match[1].toLowerCase(); + test = match[4].replace(/(\x22|\x27)/g, '\\$1'); + if (match[2] && match[4] && (type = Operators[match[2]])) { + expr = 'n=s.getAttribute(e,"' + name + '");'; + type = type.replace(/\%m/g, test); + } else if (!match[2]) { + expr = 'n=s.hasAttribute(e,"' + name + '");'; + type = 'n'; + } else if (match[2] == '!=' || match[2] == '=') { + expr = 'n=e.getAttribute("' + name + '");'; + type = 'n' + match[2] + '="' + test + '"'; + } + source = expr + 'if(' + type + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + FN = function(x) { return x; }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute, + hasAttribute: hasAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + + Dom.Operators = Operators; + Dom.Selectors = Selectors; + + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.loadResults = FN; + Dom.saveResults = FN; + Dom.setCache = FN; + + Dom.shortcuts = FN; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW3 b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW3 new file mode 100644 index 0000000..e2c5916 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW3 @@ -0,0 +1,684 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121203 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = + '\\s*(' + encoding + '+:?' + encoding + '+)' + + '\\s*(?:' + operators + '\\s*' + attrcheck + ')?\\s*', + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|\\s*|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=\\s*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|\\s*)' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^\\s*|\\s*$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\s>+~]|\\\\.)+', 'g'), + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^\s*\>\s*(.*)/, + adjacent: /^\s*\+\s*(.*)/, + relative: /^\s*\~\s*(.*)/, + ancestor: /^\s+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw SyntaxError(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + hasAttribute = root.hasAttribute ? + function(node, attribute) { + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(/\\s+/g," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + expr = ''; + type = 'false'; + name = match[1].toLowerCase(); + if (match[2] && match[4] && (type = Operators[match[2]])) { + test = match[4].replace(/(\x22|\x27)/g, '\\$1'); + expr = 'n=s.getAttribute(e,"' + name + '");'; + type = type.replace(/\%m/g, test); + } else if (!match[2]) { + expr = 'n=s.hasAttribute(e,"' + name + '");'; + type = 'n'; + } else if (match[2] == '!=' || match[2] == '=') { + expr = 'n=e.getAttribute("' + name + '");'; + type = 'n' + match[2] + '="' + match[4] + '"'; + } + source = expr + 'if(' + type + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + FN = function(x) { return x; }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute, + hasAttribute: hasAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + + Dom.Operators = Operators; + Dom.Selectors = Selectors; + + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.loadResults = FN; + Dom.saveResults = FN; + Dom.setCache = FN; + + Dom.shortcuts = FN; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW4 b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW4 new file mode 100644 index 0000000..634192b --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/OLD2/nwmatcher-base.js.NEW4 @@ -0,0 +1,691 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20121203 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw SyntaxError(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + switchContext(from || (from = doc)); + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + hasAttribute = root.hasAttribute ? + function(node, attribute) { + return node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + expr = ''; + type = 'false'; +// name = match[1]; + if (match[2] && match[4] && (type = Operators[match[2]])) { + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/g, '\\x$1'); +// expr = 'n=s.getAttribute(e,"' + name + '");'; + type = type.replace(/\%m/g, match[4]); +// } else if (!match[2]) { +// expr = 'n=s.hasAttribute(e,"' + name + '");'; +// type = 'n'; + } else if (match[2] == '!=' || match[2] == '=') { +// expr = 'n=e.getAttribute("' + name + '");'; + type = 'n' + match[2] + '="' + match[4] + '"'; + } + + expr = 'n=s.' + (match[2] ? 'get' : 'has') + 'Attribute(e,"' + match[1] + '");'; + source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}'; + +// source = expr + 'if(' + type + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + FN = function(x) { return x; }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute, + hasAttribute: hasAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + + Dom.Operators = Operators; + Dom.Selectors = Selectors; + + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.loadResults = FN; + Dom.saveResults = FN; + Dom.setCache = FN; + + Dom.shortcuts = FN; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-cache.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-cache.js new file mode 100644 index 0000000..6f8afb6 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-cache.js @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * Caching/memoization module for NWMatcher + * + * Added capabilities: + * + * - Mutation Events are feature tested and used safely + * - handle caching different document types HTML/XML/SVG + * - store result sets for different selectors / contexts + * - simultaneously control mutation on multiple documents + * + */ + +(function(global) { + + // export the public API for CommonJS implementations, + // for headless JS engines or for standard web browsers + var Dom = + // as CommonJS/NodeJS module + typeof exports == 'object' ? exports : + // create or extend NW namespace + ((global.NW || (global.NW = { })) && + (global.NW.Dom || (global.NW.Dom = { }))), + + Contexts = { }, + Results = { }, + + isEnabled = false, + isExpired = true, + isPaused = false, + + context = global.document, + root = context.documentElement, + + // last time cache initialization was called + lastCalled = 0, + + // minimum time allowed between calls to the cache initialization + minCacheRest = 15, //ms + + mutationTest = + function(type, callback) { + var isSupported = false, + root = document.documentElement, + div = document.createElement('div'), + handler = function() { isSupported = true; }; + root.insertBefore(div, root.firstChild); + div.addEventListener(type, handler, true); + if (callback && callback.call) callback(div); + div.removeEventListener(type, handler, true); + root.removeChild(div); + return isSupported; + }, + + // check for Mutation Events, DOMAttrModified should be + // enough to ensure DOMNodeInserted/DOMNodeRemoved exist + HACKED_MUTATION_EVENTS = false, + + NATIVE_MUTATION_EVENTS = root.addEventListener ? + mutationTest('DOMAttrModified', function(e) { e.setAttribute('id', 'nw'); }) : false, + + loadResults = + function(selector, from, doc, root) { + if (isEnabled && !isPaused) { + if (!isExpired) { + if (Results[selector] && Contexts[selector] === from) { + return Results[selector]; + } + } else { + // pause caching while we are getting + // hammered by dom mutations (jdalton) + now = new Date; + if ((now - lastCalled) < minCacheRest) { + isPaused = isExpired = true; + setTimeout(function() { isPaused = false; }, minCacheRest); + } else setCache(true, doc); + lastCalled = now; + } + } + return undefined; + }, + + saveResults = + function(selector, from, doc, data) { + Contexts[selector] = from; + Results[selector] = data; + return; + }, + + /*-------------------------------- CACHING ---------------------------------*/ + + // invoked by mutation events to expire cached parts + mutationWrapper = + function(event) { + var d = event.target.ownerDocument || event.target; + stopMutation(d); + expireCache(d); + }, + + // append mutation events + startMutation = + function(d) { + if (!d.isCaching && d.addEventListener) { + // FireFox/Opera/Safari/KHTML have support for Mutation Events + d.addEventListener('DOMAttrModified', mutationWrapper, true); + d.addEventListener('DOMNodeInserted', mutationWrapper, true); + d.addEventListener('DOMNodeRemoved', mutationWrapper, true); + d.isCaching = true; + } + }, + + // remove mutation events + stopMutation = + function(d) { + if (d.isCaching && d.removeEventListener) { + d.removeEventListener('DOMAttrModified', mutationWrapper, true); + d.removeEventListener('DOMNodeInserted', mutationWrapper, true); + d.removeEventListener('DOMNodeRemoved', mutationWrapper, true); + d.isCaching = false; + } + }, + + // enable/disable context caching system + // @d optional document context (iframe, xml document) + // script loading context will be used as default context + setCache = + function(enable, d) { + if (!!enable) { + isExpired = false; + startMutation(d); + } else { + isExpired = true; + stopMutation(d); + } + isEnabled = !!enable; + }, + + // expire complete cache + // can be invoked by Mutation Events or + // programmatically by other code/scripts + // document context is mandatory no checks + expireCache = + function(d) { + isExpired = true; + Contexts = { }; + Results = { }; + }; + + if (!NATIVE_MUTATION_EVENTS && root.addEventListener && Element && Element.prototype) { + if (mutationTest('DOMNodeInserted', function(e) { e.appendChild(document.createElement('div')); }) && + mutationTest('DOMNodeRemoved', function(e) { e.removeChild(e.appendChild(document.createElement('div'))); })) { + HACKED_MUTATION_EVENTS = true; + Element.prototype._setAttribute = Element.prototype.setAttribute; + Element.prototype.setAttribute = + function(name, val) { + this._setAttribute(name, val); + mutationWrapper({ + target: this, + type: 'DOMAttrModified', + attrName: name, + attrValue: val }); + }; + } + } + + isEnabled = NATIVE_MUTATION_EVENTS || HACKED_MUTATION_EVENTS; + + /*------------------------------- PUBLIC API -------------------------------*/ + + // save results into cache + Dom.saveResults = saveResults; + + // load results from cache + Dom.loadResults = loadResults; + + // expire DOM tree cache + Dom.expireCache = expireCache; + + // enable/disable cache + Dom.setCache = setCache; + +})(this); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-jquery.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-jquery.js new file mode 100644 index 0000000..b0a4ea7 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-jquery.js @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2007-2009 Diego Perini + * All rights reserved. + * + * this is just a small example to show + * how an extension for NWMatcher could be + * adapted to handle special jQuery selectors + * + * Child Selectors + * :even, :odd, :eq, :lt, :gt, :first, :last, :nth + * + * Pseudo Selectors + * :has, :button, :header, :input, :checkbox, :radio, :file, :image + * :password, :reset, :submit, :text, :hidden, :visible, :parent + * + */ + +// for structural pseudo-classes extensions +NW.Dom.registerSelector( + 'jquery:child', + /^\:((?:(nth|eq|lt|gt)\(([^()]*)\))|(?:even|odd|first|last))(.*)/i, + function(match, source, selector) { + + var status = true, ACCEPT_NODE = NW.Dom.ACCEPT_NODE; + + switch (match[1].toLowerCase()) { + case 'odd': + source = source.replace(ACCEPT_NODE, 'if((x=x^1)==0){' + ACCEPT_NODE + '}'); + break; + case 'even': + source = source.replace(ACCEPT_NODE, 'if((x=x^1)==1){' + ACCEPT_NODE + '}'); + break; + case 'first': + source = 'n=h.getElementsByTagName(e.nodeName);if(n.length&&n[0]===e){' + source + '}'; + break; + case 'last': + source = 'n=h.getElementsByTagName(e.nodeName);if(n.length&&n[n.length-1]===e){' + source + '}'; + break; + default: + switch (match[2].toLowerCase()) { + case 'nth': + source = 'n=h.getElementsByTagName(e.nodeName);if(n.length&&n[' + match[3] + ']===e){' + source + '}'; + break; + case 'eq': + source = source.replace(ACCEPT_NODE, 'if(x++==' + match[3] + '){' + ACCEPT_NODE + '}'); + break; + case 'lt': + source = source.replace(ACCEPT_NODE, 'if(x++<' + match[3] + '){' + ACCEPT_NODE + '}'); + break; + case 'gt': + source = source.replace(ACCEPT_NODE, 'if(x++>' + match[3] + '){' + ACCEPT_NODE + '}'); + break; + default: + status = false; + break; + } + break; + } + + // compiler will add this to "source" + return { + 'source': source, + 'status': status + }; + +}); + + +// for element pseudo-classes extensions +NW.Dom.registerSelector( + 'jquery:pseudo', + /^\:(has|checkbox|file|image|password|radio|reset|submit|text|button|input|header|hidden|visible|parent)(?:\(\s*(["']*)?([^'"()]*)\2\s*\))?(.*)/i, + function(match, source) { + + var status = true, ACCEPT_NODE = NW.Dom.ACCEPT_NODE; + + switch(match[1].toLowerCase()) { + case 'has': + source = source.replace(ACCEPT_NODE, 'if(e.getElementsByTagName("' + match[3].replace(/^\s|\s$/g, '') + '")[0]){' + ACCEPT_NODE + '}'); + break; + case 'checkbox': + case 'file': + case 'image': + case 'password': + case 'radio': + case 'reset': + case 'submit': + case 'text': + // :checkbox, :file, :image, :password, :radio, :reset, :submit, :text ... + source = 'if(e.type&&e.getAttribute("type")=="' + match[1] + '"){' + source + '}'; + break; + case 'button': + case 'input': + source = 'if(e.type||/button/i.test(e.nodeName)){' + source + '}'; + break; + case 'header': + source = 'if(/h[1-6]/i.test(e.nodeName)){' + source + '}'; + break; + case 'hidden': + source = 'if(!e.offsetWidth&&!e.offsetHeight){' + source + '}'; + break; + case 'visible': + source = 'if(e.offsetWidth||e.offsetHeight){' + source + '}'; + break; + case 'parent': + source += 'if(e.firstChild){' + source + '}'; + break; + default: + status = false; + break; + } + + // compiler will add this to "source" + return { + 'source': source, + 'status': status + }; + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-pseudos.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-pseudos.js new file mode 100644 index 0000000..da5a323 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-pseudos.js @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * CSS3 pseudo-classes extension for NWMatcher + * + * Added capabilities: + * + * - structural pseudo-classes + * + * :root, :empty, + * :nth-child(), nth-of-type(), + * :nth-last-child(), nth-last-of-type(), + * :first-child, :last-child, :only-child + * :first-of-type, :last-of-type, :only-of-type + * + * - negation, language, target and UI element pseudo-classes + * + * :not(), :target, :lang(), :target + * :link, :visited, :active, :focus, :hover, + * :checked, :disabled, :enabled, :selected + */ + +(function() { + + var LINK_NODES = { + 'a': 1, 'A': 1, + 'area': 1, 'AREA': 1, + 'link': 1, 'LINK': 1 + }, + + root = document.documentElement, + + contains = 'compareDocumentPosition' in root ? + function(container, element) { + return (container.compareDocumentPosition(element) & 16) == 16; + } : 'contains' in root ? + function(container, element) { + return element.nodeType == 1 && container.contains(element); + } : + function(container, element) { + while ((element = element.parentNode) && element.nodeType == 1) { + if (element === container) return true; + } + return false; + }, + + isLink = + function(element) { + return element.getAttribute('href') && LINK_NODES[element.nodeName]; + }, + + isEmpty = + function(node) { + node = node.firstChild; + while (node) { + if (node.nodeType == 3 || node.nodeName > '@') return false; + node = node.nextSibling; + } + return true; + }, + + nthElement = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling'; + while ((element = element[succ])) { + if (element.nodeName > '@') ++count; + } + return count; + }, + + nthOfType = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName; + while ((element = element[succ])) { + if (element.nodeName == type) ++count; + } + return count; + }; + + NW.Dom.Snapshot['contains'] = contains; + + NW.Dom.Snapshot['isLink'] = isLink; + NW.Dom.Snapshot['isEmpty'] = isEmpty; + NW.Dom.Snapshot['nthOfType'] = nthOfType; + NW.Dom.Snapshot['nthElement'] = nthElement; + +})(); + +NW.Dom.registerSelector( + 'nwmatcher:spseudos', + /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i, + function(match, source) { + + var a, n, b, status = true, test, type; + + switch (match[1]) { + + case 'root': + if (match[3]) + source = 'if(e===h||s.contains(h,e)){' + source + '}'; + else + source = 'if(e===h){' + source + '}'; + break; + + case 'empty': + source = 'if(s.isEmpty(e)){' + source + '}'; + break; + + default: + if (match[1] && match[2]) { + + if (match[2] == 'n') { + source = 'if(e!==h){' + source + '}'; + break; + } else if (match[2] == 'even') { + a = 2; + b = 0; + } else if (match[2] == 'odd') { + a = 2; + b = 1; + } else { + b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0); + a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0); + if (n && n[1] == '-') a = -1; + } + test = a > 1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ? + 'n==' + b : + (/last/i.test(match[1])) ? + a == -1 ? 'n>=' + b : 'n<=' + b : + a == -1 ? 'n<=' + b : 'n>=' + b; + source = + 'if(e!==h){' + + 'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' + + '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' + + 'if(' + test + '){' + source + '}' + + '}'; + + } else if (match[1]) { + + a = /first/i.test(match[1]) ? 'previous' : 'next'; + n = /only/i.test(match[1]) ? 'previous' : 'next'; + b = /first|last/i.test(match[1]); + type = /-of-type/i.test(match[1]) ? '&&n.nodeName!==e.nodeName' : '&&n.nodeName<"@"'; + source = 'if(e!==h){' + + ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source : + 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}'; + + } else { + + status = false; + + } + break; + } + + return { + 'source': source, + 'status': status + }; + +}); + +NW.Dom.registerSelector( + 'nwmatcher:dpseudos', + /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i, + (function() { + + var doc = document, + Config = NW.Dom.Config, + Tokens = NW.Dom.Tokens, + + reTrimSpace = RegExp('^\\s+|\\s+$', 'g'), + + reSimpleNot = RegExp('^((?!:not)' + + '(' + Tokens.prefixes + '|' + Tokens.identifier + + '|\\([^()]*\\))+|\\[' + Tokens.attributes + '\\])$'); + + return function(match, source) { + + var expr, status = true, test; + + switch (match[1].match(/^\w+/)[0]) { + + case 'not': + expr = match[3].replace(reTrimSpace, ''); + if (Config.SIMPLENOT && !reSimpleNot.test(expr)) { + NW.Dom.emit('Negation pseudo-class only accepts simple selectors "' + match.join('') + '"'); + } else { + if ('compatMode' in doc) { + source = 'if(!' + NW.Dom.compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}'; + } else { + source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}'; + } + } + break; + + case 'checked': + source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' + + (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') + + '){' + source + '}'; + break; + + case 'disabled': + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===true){' + source + '}'; + break; + + case 'enabled': + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===false){' + source + '}'; + break; + + case 'lang': + test = ''; + if (match[2]) test = match[2].substr(0, 2) + '-'; + source = 'do{(n=e.lang||"").toLowerCase();' + + 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' + + '(n&&(n=="' + match[2].toLowerCase() + + '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' + + '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);'; + break; + + case 'target': + n = doc.location ? doc.location.hash : ''; + if (n) { + source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}'; + } + break; + + case 'link': + source = 'if(s.isLink(e)&&!e.visited){' + source + '}'; + break; + + case 'visited': + source = 'if(s.isLink(e)&&e.visited){' + source + '}'; + break; + + case 'active': + source = 'if(e===d.activeElement){' + source + '}'; + break; + + case 'hover': + source = 'if(e===d.hoverElement){' + source + '}'; + break; + + case 'focus': + source = 'hasFocus' in doc ? + 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' : + 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}'; + break; + + case 'selected': + source = 'if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked)){' + source + '}'; + break; + + default: + status = false; + break; + } + + return { + 'source': source, + 'status': status + }; + + }; + + })()); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-shortcuts.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-shortcuts.js new file mode 100644 index 0000000..ce6ce62 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-shortcuts.js @@ -0,0 +1,35 @@ +NW.Dom.shortcuts = (function() { + + // match missing R/L context + var nextID = 0, + reLeftContext = /^[\x20\t\n\r\f]*[>+~]/, + reRightContext = /[>+~][\x20\t\n\r\f]*$/; + + return function(selector, from, alt) { + + // add left context if missing + if (reLeftContext.test(selector)) { + if (from.nodeType == 9) { + selector = '* ' + selector; + } else if (/html|body/i.test(from.nodeName)) { + selector = from.nodeName + ' ' + selector; + } else if (alt) { + selector = NW.Dom.shortcuts(selector, alt); + } else if (from.nodeType == 1 && from.id) { + selector = '#' + from.id + ' ' + selector; + } else { + ++nextID; + selector = '#' + (from.id = 'NW' + nextID) + ' ' + selector; + //NW.Dom.emit('Unable to resolve a context for the shortcut selector "' + selector + '"'); + } + } + + // add right context if missing + if (reRightContext.test(selector)) { + selector += ' *'; + } + + return selector; + }; + +})(); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-thin.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-thin.js new file mode 100644 index 0000000..184170b --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-thin.js @@ -0,0 +1,7 @@ +/*! + * NWMatcher 1.3.0 - Fast CSS3 Selector Engine + * Copyright (C) 2007-2012 Diego Perini + * See http://nwbox.com/license + */ +(function(d,e){if(typeof module==='object'&&typeof exports==='object'){module.exports=function(b){var a={};e(b,a);return a}}else{if(!d.NW){d.NW={}}if(!d.NW.Dom){d.NW.Dom={}}e(d,d.NW.Dom)}})(this,function(x,bn){var bH='nwmatcher-1.3.0',g=bn,i=x.document,t=i.documentElement,bI=[].slice,bc,J,y,z,u,bd,be,bf,bg,K='[#.:]?',bh='([~*^$|!]?={1})',p='[\\x20\\t\\n\\r\\f]*',bi='[\\x20]|[>+~][^>+~]',bj='(?:[-+]?\\d*n)?[-+]?\\d*',L='"[^"]*"'+"|'[^']*'",M='\\[.*\\]|\\(.*\\)|\\{.*\\}',n='(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)',A='(?:-?[_0-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+',bk='('+L+'|'+A+')',v=p+'('+n+'+:?'+n+'+)'+p+'(?:'+bh+p+bk+')?'+p,bo=v.replace(bk,'([\\x22\\x27]*)((?:\\\\?.)*?)\\3'),B='((?:'+bj+'|'+L+'|'+K+'|'+n+'+|\\['+v+'\\]|\\(.+\\)|'+p+'|,)+)',bp='.+',N='(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])(\\*|(?:'+K+A+')|'+bi+'|\\['+v+'\\]|\\('+B+'\\)|\\{'+bp+'\\}|(?:,|'+p+'))+',bq=N.replace(B,'.*'),O=RegExp(N,'g'),P=RegExp('^'+p+'|'+p+'$','g'),Q=RegExp('([^,\\\\()[\\]]+|\\[[^[\\]]*\\]|\\[.*\\]|\\([^()]+\\)|\\(.*\\)|\\{[^{}]+\\}|\\{.*\\}|\\\\.)+','g'),br=RegExp('(\\['+v+'\\]|\\('+B+'\\)|[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+','g'),bs=/[\x20\t\n\r\f]+/g,bt=RegExp(A+'|^$'),bu={checked:1,disabled:1,ismap:1,multiple:1,readonly:1,selected:1},bl={value:'defaultValue',checked:'defaultChecked',selected:'defaultSelected'},bv={action:2,cite:2,codebase:2,data:2,href:2,longdesc:2,lowsrc:2,src:2,usemap:2},s={},w={'=':"n=='%m'",'^=':"n.indexOf('%m')==0",'*=':"n.indexOf('%m')>-1",'|=':"(n+'-').indexOf('%m-')==0",'~=':"(' '+n+' ').indexOf(' %m ')>-1",'$=':"n.substr(n.length-'%m'.length)=='%m'"},C={ID:RegExp('^\\*?#('+n+'+)|'+M),TAG:RegExp('^('+n+'+)|'+M),CLASS:RegExp('^\\*?\\.('+n+'+$)|'+M)},q={universal:/^\*(.*)/,id:RegExp('^#('+n+'+)(.*)'),tagName:RegExp('^('+n+'+)(.*)'),className:RegExp('^\\.('+n+'+)(.*)'),attribute:RegExp('^\\['+bo+'\\](.*)'),children:/^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/,adjacent:/^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/,relative:/^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/,ancestor:/^[\x20\t\n\r\f]+(.*)/},R,r,bw='getElementsByTagName'in i,bx='getElementsByClassName'in i,S=typeof i.addEventListener!='function',by={'href':1,'lang':1,'src':1,'style':1,'title':1,'type':1,'xmlns':1,'xml:lang':1,'xml:space':1},bz=S?'.toUpperCase()':'',T='r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;',bA=S?'if(e.nodeName<"A")continue;':'',l={CACHING:false,SIMPLENOT:true,UNIQUE_ID:true,USE_HTML5:true,VERBOSITY:true},bB=function(b){if(typeof b=='string'){return l[b]}if(typeof b!='object'){return false}for(var a in b){l[a]=!!b[a];if(a=='SIMPLENOT'){U={};D={};V={};E={}}}O=RegExp(l.SIMPLENOT?N:bq,'g');return true},bC=function(b,a,d){var e=-1,h;while((h=a[++e])){if(false===d(b[b.length]=h)){break}}return b},m=function(b){if(l.VERBOSITY){throw Error(b);}if(x.console&&x.console.log){x.console.log(b)}},F=function(a,d){var e=i;z=a;i=a.ownerDocument||a;if(d||e!==i){t=i.documentElement;r=i.createElement('DiV').nodeName=='DiV';R=!r&&typeof i.compatMode=='string'?i.compatMode.indexOf('CSS')<0:(function(){var b=document.createElement('div').style;return b&&(b.width=1)&&b.width=='1px'})();l.CACHING&&g.setCache(true,i)}},W=function(b,a){var d=0,e=null;while((e=a[d])){if(e.getAttribute('id')==b){break}++d}return e},G=!('fileSize'in i)?function(b,a){b=b.replace(/\\([^\\]{1})/g,'$1');return a.getElementById&&a.getElementById(b)||W(b,a.getElementsByTagName('*'))}:function(b,a){var d=null;b=b.replace(/\\([^\\]{1})/g,'$1');if(r||a.nodeType!=9){return W(b,a.getElementsByTagName('*'))}if((d=a.getElementById(b))&&d.name==b&&a.getElementsByName){return W(b,a.getElementsByName(b))}return d},bD=function(b,a){a||(a=i);if(z!==a){F(a)}return G(b,a)},bE=function(b,a){a=a.toLowerCase();if(typeof b[a]=='object'){return b.attributes[a]&&b.attributes[a].value||''}return(a=='type'?b.getAttribute(a)||'':bv[a]?b.getAttribute(a,2)||'':bu[a]?b.getAttribute(a)?a:'false':((b=b.getAttributeNode(a))&&b.value)||'')},bF=t.hasAttribute?function(b,a){return b.hasAttribute(a)}:function(b,a){a=a.toLowerCase();if(bl[a]){return!!b[bl[a]]}b=b.getAttributeNode(a);return!!(b&&b.specified)},X=function(b,a,d){var e=typeof b=='string'?b.match(Q):b;typeof a=='string'||(a='');if(e.length==1){a+=bm(e[0],d?T:'f&&f(k);return true;',d)}else{var h=-1,c={},f;while((f=e[++h])){f=f.replace(P,'');if(!c[f]&&(c[f]=true)){a+=bm(f,d?T:'f&&f(k);return true;',d)}}}if(d)return Function('c,s,r,d,h,g,f,v','var N,n,x=0,k=-1,e;main:while((e=c[++k])){'+a+'}return r;');else return Function('e,s,r,d,h,g,f,v','var N,n,x=0,k=e;'+a+'return false;')},H='var z=v[@]||(v[@]=[]),l=z.length-1;while(l>=0&&z[l]!==e)--l;if(l!==-1){break;}z[z.length]=e;',bm=function(b,a,d){var e=0,h,c,f,j,k,o,Y;while(b){e++;if((c=b.match(q.universal))){h=''}else if((c=b.match(q.id))){a='if('+(r?'s.getAttribute(e,"id")':'(e.submit?s.getAttribute(e,"id"):e.id)')+'=="'+c[1]+'"){'+a+'}'}else if((c=b.match(q.tagName))){a='if(e.nodeName'+(r?'=="'+c[1]+'"':bz+'=="'+c[1].toUpperCase()+'"')+'){'+a+'}'}else if((c=b.match(q.className))){a='if((n='+(r?'e.getAttribute("class")':'e.className')+')&&n.length&&(" "+'+(R?'n.toLowerCase()':'n')+'.replace('+bs+'," ")+" ").indexOf(" '+(R?c[1].toLowerCase():c[1])+' ")>-1){'+a+'}'}else if((c=b.match(q.attribute))){if(c[2]&&!w[c[2]]){m('Unsupported operator in attribute selectors "'+b+'"');return''}o='false';if(c[4]){Y=by[c[1].toLowerCase()];c[4]=(Y?c[4].toLowerCase():c[4]).replace(/\\([0-9a-f]{2,2})/g,'\\x$1').replace(/(\x22|\x27)/g,'\\$1')}if(c[2]&&c[4]&&(o=w[c[2]])){o=o.replace(/\%m/g,c[4])}else if(c[2]=='!='||c[2]=='='){o='n'+c[2]+'="'+c[4]+'"'}h='n=s.'+(c[2]?'get':'has')+'Attribute(e,"'+c[1]+'")'+(Y?'.toLowerCase();':';');a=h+'if('+(c[2]?o:'n')+'){'+a+'}'}else if((c=b.match(q.adjacent))){a=(d?'':H.replace(/@/g,e))+a;a='var N'+e+'=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){'+a+'break;}}e=N'+e+';'}else if((c=b.match(q.relative))){a=(d?'':H.replace(/@/g,e))+a;a='var N'+e+'=e;e=e.parentNode.firstChild;while(e&&e!==N'+e+'){if(e.nodeName>"@"){'+a+'}e=e.nextSibling;}e=N'+e+';'}else if((c=b.match(q.children))){a=(d?'':H.replace(/@/g,e))+a;a='var N'+e+'=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){'+a+'break;}e=N'+e+';'}else if((c=b.match(q.ancestor))){a=(d?'':H.replace(/@/g,e))+a;a='var N'+e+'=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){'+a+'}e=N'+e+';'}else{h=false;k=false;for(h in s){if((c=b.match(s[h].Expression))&&c[1]){j=s[h].Callback(c,a);a=j.source;k=j.status;if(k){break}}}if(!k){m('Unknown pseudo-class selector "'+b+'"');return''}if(!h){m('Unknown token in selector "'+b+'"');return''}}if(!c){m('Invalid syntax in selector "'+b+'"');return''}b=c&&c[c.length-1]}return a},Z=function(b,a,d,e){var h;if(!(b&&b.nodeName>'@')){m('Invalid element argument');return false}else if(!a||typeof a!='string'){m('Invalid selector argument');return false}else if(z!==d){F(d||(d=b.ownerDocument))}a=a.replace(P,'');l.SHORTCUTS&&(a=NW.Dom.shortcuts(a,b,d));if(bd!=a){if((h=a.match(O))&&h[0]==a){bc=(h=a.match(Q)).length<2;bd=a;bf=h}else{m('The string "'+a+'", is not a valid CSS selector');return false}}else h=bf;if(!D[a]||U[a]!==d){D[a]=X(bc?[a]:h,'',false);U[a]=d}return D[a](b,ba,[],i,t,d,e,{})},bG=function(b,a){return bb(b,a,function(){return false})[0]||null},bb=function(b,a,d){var e,h,c,f,j,k,o=b;if(arguments.length===0){m('Not enough arguments');return[]}else if(typeof b!='string'){return[]}else if(!(/[>+~*\w\u00a1-\uffff]/.test(b))){m('Invalid or illegal selector string');return[]}else if(a&&!(/1|9|11/).test(a.nodeType)){m('Invalid or illegal context element');return[]}else if(z!==a){F(a||(a=i))}if(l.CACHING&&(f=g.loadResults(o,a,i,t))){return d?bC([],f,d):f}b=b.replace(P,'');l.SHORTCUTS&&(b=NW.Dom.shortcuts(b,a));if((h=be!=b)){if((j=b.match(O))&&j[0]==b){J=(j=b.match(Q)).length<2;be=b;bg=j}else{m('The string "'+b+'", is not a valid CSS selector');return[]}}else j=bg;if(a.nodeType==11){f=a.childNodes}else if(J){if(h){j=b.match(br);k=j[j.length-1];y=k.split(':not')[0];u=b.length-k.length}if(l.UNIQUE_ID&&(j=y.match(C.ID))&&(k=j[1])){if((c=G(k,a))){if(Z(c,b)){d&&d(c);f=[c]}else f=[]}}else if(l.UNIQUE_ID&&(j=b.match(C.ID))&&(k=j[1])){if((c=G(k,i))){if('#'+k==b){d&&d(c);f=[c]}else if(/[>+~]/.test(b)){a=c.parentNode}else{a=c}}else f=[]}if(f){l.CACHING&&g.saveResults(o,a,i,f);return f}if(!r&&bw&&(j=y.match(C.TAG))&&(k=j[1])){if((f=a.getElementsByTagName(k)).length===0)return[];b=b.slice(0,u)+b.slice(u).replace(k,'*')}else if(!r&&bx&&(j=y.match(C.CLASS))&&(k=j[1])){if((f=a.getElementsByClassName(k.replace(/\\([^\\]{1})/g,'$1'))).length===0)return[];b=b.slice(0,u)+b.slice(u).replace('.'+k,bt.test(b.charAt(b.indexOf(k)-1))?'':'*')}}if(!f){if(S){f=/^(?:applet|object)$/i.test(a.nodeName)?a.childNodes:a.all}else{f=a.getElementsByTagName('*')}}if(!E[b]||V[b]!==a){E[b]=X(J?[b]:j,bA,true);V[b]=a}f=E[b](f,ba,[],i,t,a,d,{});l.CACHING&&g.saveResults(o,a,i,f);return f},I=function(b){return b},U={},D={},V={},E={},ba={byId:G,match:Z,select:bb,getAttribute:bE,hasAttribute:bF};Tokens={prefixes:K,encoding:n,operators:bh,whitespace:p,identifier:A,attributes:v,combinators:bi,pseudoclass:B,pseudoparms:bj,quotedvalue:L};g.ACCEPT_NODE=T;g.emit=m;g.byId=bD;g.match=Z;g.first=bG;g.select=bb;g.compile=X;g.configure=bB;g.Config=l;g.Operators=w;g.Selectors=s;g.Snapshot=ba;g.Tokens=Tokens;g.setCache=I;g.shortcuts=I;g.loadResults=I;g.saveResults=I;g.registerOperator=function(b,a){w[b]||(w[b]=a)};g.registerSelector=function(b,a,d){s[b]||(s[b]={Expression:a,Callback:d})};F(i,true)}); +(function(){var h={'a':1,'A':1,'area':1,'AREA':1,'link':1,'LINK':1},g=document.documentElement,f='compareDocumentPosition'in g?function(b,a){return(b.compareDocumentPosition(a)&16)==16}:'contains'in g?function(b,a){return a.nodeType==1&&b.contains(a)}:function(b,a){while((a=a.parentNode)&&a.nodeType==1){if(a===b)return true}return false},i=function(b){return b.getAttribute('href')&&h[b.nodeName]},j=function(b){b=b.firstChild;while(b){if(b.nodeType==3||b.nodeName>'@')return false;b=b.nextSibling}return true},k=function(b,a){var c=1,e=a?'nextSibling':'previousSibling';while((b=b[e])){if(b.nodeName>'@')++c}return c},l=function(b,a){var c=1,e=a?'nextSibling':'previousSibling',d=b.nodeName;while((b=b[e])){if(b.nodeName==d)++c}return c};NW.Dom.Snapshot['contains']=f;NW.Dom.Snapshot['isLink']=i;NW.Dom.Snapshot['isEmpty']=j;NW.Dom.Snapshot['nthOfType']=l;NW.Dom.Snapshot['nthElement']=k})();NW.Dom.registerSelector('nwmatcher:spseudos',/^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i,function(b,a){var c,e,d,h=true,g,f;switch(b[1]){case'root':if(b[3])a='if(e===h||s.contains(h,e)){'+a+'}';else a='if(e===h){'+a+'}';break;case'empty':a='if(s.isEmpty(e)){'+a+'}';break;default:if(b[1]&&b[2]){if(b[2]=='n'){a='if(e!==h){'+a+'}';break}else if(b[2]=='even'){c=2;d=0}else if(b[2]=='odd'){c=2;d=1}else{d=((e=b[2].match(/(-?\d+)$/))?parseInt(e[1],10):0);c=((e=b[2].match(/(-?\d*)n/i))?parseInt(e[1],10):0);if(e&&e[1]=='-')c=-1}g=c>1?(/last/i.test(b[1]))?'(n-('+d+'))%'+c+'==0':'n>='+d+'&&(n-('+d+'))%'+c+'==0':c<-1?(/last/i.test(b[1]))?'(n-('+d+'))%'+c+'==0':'n<='+d+'&&(n-('+d+'))%'+c+'==0':c===0?'n=='+d:(/last/i.test(b[1]))?c==-1?'n>='+d:'n<='+d:c==-1?'n<='+d:'n>='+d;a='if(e!==h){n=s['+(/-of-type/i.test(b[1])?'"nthOfType"':'"nthElement"')+'](e,'+(/last/i.test(b[1])?'true':'false')+');if('+g+'){'+a+'}}'}else if(b[1]){c=/first/i.test(b[1])?'previous':'next';e=/only/i.test(b[1])?'previous':'next';d=/first|last/i.test(b[1]);f=/-of-type/i.test(b[1])?'&&n.nodeName!==e.nodeName':'&&n.nodeName<"@"';a='if(e!==h){'+('n=e;while((n=n.'+c+'Sibling)'+f+');if(!n){'+(d?a:'n=e;while((n=n.'+e+'Sibling)'+f+');if(!n){'+a+'}')+'}')+'}'}else{h=false}break}return{'source':a,'status':h}});NW.Dom.registerSelector('nwmatcher:dpseudos',/^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i,(function(){var h=document,g=NW.Dom.Config,f=NW.Dom.Tokens,i=RegExp('^'+f.whitespace+'|'+f.whitespace+'$','g'),j=RegExp('^((?!:not)('+f.prefixes+'|'+f.identifier+'|\\([^()]*\\))+|\\['+f.attributes+'\\])$');return function(b,a){var c,e=true,d;switch(b[1].match(/^\w+/)[0]){case'not':c=b[3].replace(i,'');if(g.SIMPLENOT&&!j.test(c)){NW.Dom.emit('Negation pseudo-class only accepts simple selectors "'+b.join('')+'"')}else{if('compatMode'in h){a='if(!'+NW.Dom.compile(c,'',false)+'(e,s,r,d,h,g)){'+a+'}'}else{a='if(!s.match(e, "'+c.replace(/\x22/g,'\\"')+'",g)){'+a+'}'}}break;case'checked':a='if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)'+(g.USE_HTML5?'||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))':'')+'){'+a+'}';break;case'disabled':a='if(((typeof e.form!=="undefined"'+(g.USE_HTML5?'':'&&!(/^hidden$/i).test(e.type)')+')||s.isLink(e))&&e.disabled===true){'+a+'}';break;case'enabled':a='if(((typeof e.form!=="undefined"'+(g.USE_HTML5?'':'&&!(/^hidden$/i).test(e.type)')+')||s.isLink(e))&&e.disabled===false){'+a+'}';break;case'lang':d='';if(b[2])d=b[2].substr(0,2)+'-';a='do{(n=e.lang||"").toLowerCase();if((n==""&&h.lang=="'+b[2].toLowerCase()+'")||(n&&(n=="'+b[2].toLowerCase()+'"||n.substr(0,3)=="'+d.toLowerCase()+'"))){'+a+'break;}}while((e=e.parentNode)&&e!==g);';break;case'target':n=h.location?h.location.hash:'';if(n){a='if(e.id=="'+n.slice(1)+'"){'+a+'}'}break;case'link':a='if(s.isLink(e)&&!e.visited){'+a+'}';break;case'visited':a='if(s.isLink(e)&&e.visited){'+a+'}';break;case'active':a='if(e===d.activeElement){'+a+'}';break;case'hover':a='if(e===d.hoverElement){'+a+'}';break;case'focus':a='hasFocus'in h?'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){'+a+'}':'if(e===d.activeElement&&(e.type||e.href)){'+a+'}';break;case'selected':a='if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked)){'+a+'}';break;default:e=false;break}return{'source':a,'status':e}}})()); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-traversal.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-traversal.js new file mode 100644 index 0000000..9d2b62f --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-traversal.js @@ -0,0 +1,90 @@ +/* + * Element Traversal methods from Juriy Zaytsev (kangax) + * used to emulate Prototype up/down/previous/next methods + */ + +(function(D){ + + // TODO: all of this needs tests + var match = D.match, select = D.select, root = document.documentElement, + + // Use the Element Traversal API if available. + nextElement = 'nextElementSibling', + previousElement = 'previousElementSibling', + parentElement = 'parentElement'; + + // Fall back to the DOM Level 1 API. + if (!(nextElement in root)) nextElement = 'nextSibling'; + if (!(previousElement in root)) previousElement = 'previousSibling'; + if (!(parentElement in root)) parentElement = 'parentNode'; + + function walkElements(property, element, expr) { + var i = 0, isIndex = typeof expr == 'number'; + if (typeof expr == 'undefined') { + isIndex = true; + expr = 0; + } + while ((element = element[property])) { + if (element.nodeType != 1) continue; + if (isIndex) { + ++i; + if (i == expr) return element; + } else if (match(element, expr)) { + return element; + } + } + return null; + } + + /** + * @method up + * @param {HTMLElement} element element to walk from + * @param {String | Number} expr CSS expression or an index + * @return {HTMLElement | null} + */ + function up(element, expr) { + return walkElements(parentElement, element, expr); + } + /** + * @method next + * @param {HTMLElement} element element to walk from + * @param {String | Number} expr CSS expression or an index + * @return {HTMLElement | null} + */ + function next(element, expr) { + return walkElements(nextElement, element, expr); + } + /** + * @method previous + * @param {HTMLElement} element element to walk from + * @param {String | Number} expr CSS expression or an index + * @return {HTMLElement | null} + */ + function previous(element, expr) { + return walkElements(previousElement, element, expr); + } + /** + * @method down + * @param {HTMLElement} element element to walk from + * @param {String | Number} expr CSS expression or an index + * @return {HTMLElement | null} + */ + function down(element, expr) { + var isIndex = typeof expr == 'number', descendants, index, descendant; + if (expr === null) { + element = element.firstChild; + while (element && element.nodeType != 1) element = element[nextElement]; + return element; + } + if (!isIndex && match(element, expr) || isIndex && expr === 0) return element; + descendants = select('*', element); + if (isIndex) return descendants[expr] || null; + index = 0; + while ((descendant = descendants[index]) && !match(descendant, expr)) { ++index; } + return descendant || null; + } + D.up = up; + D.down = down; + D.next = next; + D.previous = previous; +})(NW.Dom); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-webforms.js b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-webforms.js new file mode 100644 index 0000000..f8fabc2 --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/modules/nwmatcher-webforms.js @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007-2010 Diego Perini + * All rights reserved. + * + * this is just a small example to show + * how an extension for NWMatcher could be + * adapted to handle WebForms/HTML5 selectors + * + * Pseudo Selectors + * :default, :indeterminate, :optional, :required, + * :valid, :invalid, :in-range, :out-of-range, + * :read-only, :read-write + * :has, :matches (not yet in a defined specification) + * + */ + +// for UI pseudo-classes extensions (WebForms/HTML5) +NW.Dom.registerSelector( + 'html5:pseudos', + /^\:(default|indeterminate|optional|required|valid|invalid|in-range|out-of-range|read-only|read-write)(.*)/, + function(match, source) { + + var status = true, + + HTML5PseudoClasses = { + 'default': 4, 'indeterminate': 4, 'invalid': 4, 'valid': 4, + 'optional': 4, 'required': 4, 'read-write': 4, 'read-only': 4 + }; + + switch (match[1]) { + + // HTML5 UI element states (form controls) + case 'default': + // only radio buttons, check boxes and option elements + source = 'if(((typeof e.form!=="undefined"&&(/radio|checkbox/i).test(e.type))||/option/i.test(e.nodeName))&&(e.defaultChecked||e.defaultSelected)){' + source + '}'; + break; + + case 'indeterminate': + // only radio buttons, check boxes and option elements + source = 'if(typeof e.form!=="undefined"&&(/radio|checkbox/i).test(e.type)&&s.select("[checked]",e.form).length===0){' + source + '}'; + break; + + case 'optional': + // only fields for which "required" applies + source = 'if(typeof e.form!=="undefined"&&typeof e.required!="undefined"&&!e.required){' + source + '}'; + break; + + case 'required': + // only fields for which "required" applies + source = 'if(typeof e.form!=="undefined"&&typeof e.required!="undefined"&&e.required){' + source + '}'; + break; + + case 'read-write': + // only fields for which "readOnly" applies + source = 'if(typeof e.form!=="undefined"&&typeof e.readOnly!="undefined"&&!e.readOnly){' + source + '}'; + break; + + case 'read-only': + // only fields for which "readOnly" applies + source = 'if(typeof e.form!=="undefined"&&typeof e.readOnly!="undefined"&&e.readOnly){' + source + '}'; + break; + + case 'invalid': + // only fields for which validity applies + source = 'if(typeof e.form!=="undefined"&&typeof e.validity=="object"&&!e.validity.valid){' + source + '}'; + break; + + case 'valid': + // only fields for which validity applies + source = 'if(typeof e.form!=="undefined"&&typeof e.validity=="object"&&e.validity.valid){' + source + '}'; + break; + + case 'in-range': + // only fields for which validity applies + source = 'if(typeof e.form!=="undefined"&&' + + '(s.getAttribute(e,"min")||s.getAttribute(e,"max"))&&' + + 'typeof e.validity=="object"&&!e.validity.typeMismatch&&' + + '!e.validity.rangeUnderflow&&!e.validity.rangeOverflow){' + source + '}'; + break; + + case 'out-of-range': + // only fields for which validity applies + source = 'if(typeof e.form!=="undefined"&&' + + '(s.getAttribute(e,"min")||s.getAttribute(e,"max"))&&' + + 'typeof e.validity=="object"&&(e.validity.rangeUnderflow||e.validity.rangeOverflow)){' + source + '}'; + break; + + default: + status = false; + break; + + } + + // compiler will add this to "source" + return { + 'source': source, + 'status': status + }; + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/nwmatcher-base.js b/node_modules/jsdom/node_modules/nwmatcher/src/nwmatcher-base.js new file mode 100644 index 0000000..43e7e7f --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/nwmatcher-base.js @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher-base.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20130110 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + doc = global.document, + root = doc.documentElement, + + slice = [ ].slice, + + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + prefixes = '[#.:]?', + operators = '([~*^$|!]?={1})', + whitespace = '[\\x20\\t\\n\\r\\f]*', + combinators = '[\\x20]|[>+~][^>+~]', + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + quotedvalue = '"[^"]*"' + "|'[^']*'", + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + pseudoclass = '((?:' + + pseudoparms + '|' + quotedvalue + '|' + + prefixes + '|' + encoding + '+|' + + '\\[' + attributes + '\\]|' + + '\\(.+\\)|' + whitespace + '|' + + ',)+)', + + extensions = '.+', + + standardValidator = + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + '(' + + '\\*' + + '|(?:' + prefixes + identifier + ')' + + '|' + combinators + + '|\\[' + attributes + '\\]' + + '|\\(' + pseudoclass + '\\)' + + '|\\{' + extensions + '\\}' + + '|(?:,|' + whitespace + ')' + + ')+', + + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + reValidator = RegExp(standardValidator, 'g'), + + reTrimSpaces = RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + reSplitGroup = RegExp('(' + + '[^,\\\\()[\\]]+' + + '|\\[[^[\\]]*\\]|\\[.*\\]' + + '|\\([^()]+\\)|\\(.*\\)' + + '|\\{[^{}]+\\}|\\{.*\\}' + + '|\\\\.' + + ')+', 'g'), + + reSplitToken = RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\n\\r\\f>+~]|\\\\.)+', 'g'), + + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = RegExp(identifier + '|^$'), + + ATTR_BOOLEAN = { + checked: 1, disabled: 1, ismap: 1, + multiple: 1, readonly: 1, selected: 1 + }, + + ATTR_DEFAULT = { + value: 'defaultValue', + checked: 'defaultChecked', + selected: 'defaultSelected' + }, + + ATTR_URIDATA = { + action: 2, cite: 2, codebase: 2, data: 2, href: 2, + longdesc: 2, lowsrc: 2, src: 2, usemap: 2 + }, + + Selectors = { }, + + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + Optimize = { + ID: RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + Patterns = { + universal: /^\*(.*)/, + id: RegExp('^#(' + encoding + '+)(.*)'), + tagName: RegExp('^(' + encoding + '+)(.*)'), + className: RegExp('^\\.(' + encoding + '+)(.*)'), + attribute: RegExp('^\\[' + attrmatcher + '\\](.*)'), + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + ancestor: /^[\x20\t\n\r\f]+(.*)/ + }, + + QUIRKS_MODE, + XML_DOCUMENT, + + GEBTN = 'getElementsByTagName' in doc, + GEBCN = 'getElementsByClassName' in doc, + + IE_LT_9 = typeof doc.addEventListener != 'function', + + INSENSITIVE_MAP = { + 'href': 1, 'lang': 1, 'src': 1, 'style': 1, 'title': 1, + 'type': 1, 'xmlns': 1, 'xml:lang': 1, 'xml:space': 1 + }, + + TO_UPPER_CASE = IE_LT_9 ? '.toUpperCase()' : '', + + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + REJECT_NODE = IE_LT_9 ? 'if(e.nodeName<"A")continue;' : '', + + Config = { + CACHING: false, + SIMPLENOT: true, + UNIQUE_ID: true, + USE_HTML5: true, + VERBOSITY: true + }, + + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + } + } + reValidator = RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + emit = + function(message) { + if (Config.VERBOSITY) { throw Error(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + switchContext = + function(from, force) { + var oldDoc = doc; + lastContext = from; + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + root = doc.documentElement; + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = document.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + byIdRaw = + function(id, elements) { + var i = 0, element = null; + while ((element = elements[i])) { + if (element.getAttribute('id') == id) { + break; + } + ++i; + } + return element; + }, + + _byId = !('fileSize' in doc) ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + byId = + function(id, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byId(id, from); + }, + + getAttribute = + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + attribute == 'type' ? node.getAttribute(attribute) || '' : + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + hasAttribute = root.hasAttribute ? + function(node, attribute) { + return node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + node = node.getAttributeNode(attribute); + return !!(node && node.specified); + }, + + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) + return Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + else + return Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + }, + + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + compileSelector = + function(selector, source, mode) { + + var k = 0, expr, match, name, result, status, test, type; + + while (selector) { + + k++; + + if ((match = selector.match(Patterns.universal))) { + expr = ''; + } + + else if ((match = selector.match(Patterns.id))) { + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.tagName))) { + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : TO_UPPER_CASE + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.className))) { + source = 'if((n=' + (XML_DOCUMENT ? + 'e.getAttribute("class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.attribute))) { + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + test = 'false'; + if (match[4]) { + type = INSENSITIVE_MAP[match[1].toLowerCase()]; + match[4] = + (type ? match[4].toLowerCase() : match[4]) + .replace(/\\([0-9a-f]{2,2})/g, '\\x$1') + .replace(/(\x22|\x27)/g, '\\$1'); + } + if (match[2] && match[4] && (test = Operators[match[2]])) { + test = test.replace(/\%m/g, match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + test = 'n' + match[2] + '="' + match[4] + '"'; + } + expr = 'n=s.' + (match[2] ? 'get' : 'has') + 'Attribute(e,"' + match[1] + '")' + (type ? '.toLowerCase();' : ';'); + source = expr + 'if(' + (match[2] ? test : 'n') + '){' + source + '}'; + } + + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;e=e.parentNode.firstChild;while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + else { + + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + if (!status) { + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + selector = match && match[match.length - 1]; + } + + return source; + }, + + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (lastContext !== from) { + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (isSingleSelect) { + + if (changed) { + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + lastSlice = token.split(':not')[0]; + lastPosition = selector.length - token.length; + } + + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!XML_DOCUMENT && GEBTN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = from.getElementsByTagName(token)).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if (!XML_DOCUMENT && GEBCN && (parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = from.getElementsByClassName(token.replace(/\\([^\\]{1})/g, '$1'))).length === 0) return [ ]; + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, + reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1)) ? '' : '*'); + } + + } + + if (!elements) { + if (IE_LT_9) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? + from.childNodes : from.all; + } else { + elements = from.getElementsByTagName('*'); + } + } + + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, REJECT_NODE, true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + FN = function(x) { return x; }, + + matchContexts = { }, + matchResolvers = { }, + + selectContexts = { }, + selectResolvers = { }, + + Snapshot = { + byId: _byId, + match: match, + select: select, + getAttribute: getAttribute, + hasAttribute: hasAttribute + }; + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + Dom.ACCEPT_NODE = ACCEPT_NODE; + + Dom.emit = emit; + + Dom.byId = byId; + Dom.match = match; + Dom.first = first; + Dom.select = select; + Dom.compile = compile; + Dom.configure = configure; + + Dom.Config = Config; + + Dom.Operators = Operators; + Dom.Selectors = Selectors; + + Dom.Snapshot = Snapshot; + Dom.Tokens = Tokens; + + Dom.setCache = FN; + Dom.shortcuts = FN; + Dom.loadResults = FN; + Dom.saveResults = FN; + + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/nwmatcher/src/nwmatcher.js b/node_modules/jsdom/node_modules/nwmatcher/src/nwmatcher.js new file mode 100644 index 0000000..63873ea --- /dev/null +++ b/node_modules/jsdom/node_modules/nwmatcher/src/nwmatcher.js @@ -0,0 +1,1659 @@ +/* + * Copyright (C) 2007-2012 Diego Perini + * All rights reserved. + * + * nwmatcher.js - A fast CSS selector engine and matcher + * + * Author: Diego Perini + * Version: 1.3.0 + * Created: 20070722 + * Release: 20130110 + * + * License: + * http://javascript.nwbox.com/NWMatcher/MIT-LICENSE + * Download: + * http://javascript.nwbox.com/NWMatcher/nwmatcher.js + */ + +(function(global, factory) { + + if (typeof module === 'object' && typeof exports === 'object') { + // in a Node.js environment, the nwmatcher functions will operate on + // the passed "browserGlobal" and will be returned in an object + module.exports = function (browserGlobal) { + var exports = { }; + factory(browserGlobal, exports); + return exports; + }; + } else { + // in a browser environment, the nwmatcher functions will operate on + // the "global" loading them and be attached to "global.NW.Dom" + if (!global.NW) { + global.NW = { }; + } + if (!global.NW.Dom) { + global.NW.Dom = { }; + } + factory(global, global.NW.Dom); + } + +})(this, function(global, exports) { + + var version = 'nwmatcher-1.3.0', + + Dom = exports, + + // processing context & root element + doc = global.document, + root = doc.documentElement, + + // save utility methods references + slice = [ ].slice, + string = { }.toString, + + // persist previous parsed data + isSingleMatch, + isSingleSelect, + + lastSlice, + lastContext, + lastPosition, + + lastMatcher, + lastSelector, + + lastPartsMatch, + lastPartsSelect, + + // accepted prefix identifiers + // (id, class & pseudo-class) + prefixes = '[#.:]?', + + // accepted attribute operators + operators = '([~*^$|!]?={1})', + + // accepted whitespace characters + whitespace = '[\\x20\\t\\n\\r\\f]*', + + // 4 combinators F E, F>E, F+E, F~E + combinators = '[\\x20]|[>+~][^>+~]', + + // an+b format params for pseudo-classes + pseudoparms = '(?:[-+]?\\d*n)?[-+]?\\d*', + + // CSS quoted string values + quotedvalue = '"[^"]*"' + "|'[^']*'", + + // skip round brackets groups + skipround = '\\([^()]+\\)|\\(.*\\)', + // skip curly brackets groups + skipcurly = '\\{[^{}]+\\}|\\{.*\\}', + // skip square brackets groups + skipsquare = '\\[[^[\\]]*\\]|\\[.*\\]', + + // skip [ ], ( ), { } brackets groups + skipgroup = '\\[.*\\]|\\(.*\\)|\\{.*\\}', + + // http://www.w3.org/TR/css3-syntax/#characters + // unicode/ISO 10646 characters 161 and higher + // NOTE: Safari 2.0.x crashes with escaped (\\) + // Unicode ranges in regular expressions so we + // use a negated character range class instead + encoding = '(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)', + + // CSS identifier syntax + identifier = '(?:-?[_a-zA-Z]{1}[-\\w]*|[^\\x00-\\xa0]+|\\\\.+)+', + + // build attribute string + attrcheck = '(' + quotedvalue + '|' + identifier + ')', + attributes = whitespace + '(' + encoding + '+:?' + encoding + '+)' + + whitespace + '(?:' + operators + whitespace + attrcheck + ')?' + whitespace, + attrmatcher = attributes.replace(attrcheck, '([\\x22\\x27]*)((?:\\\\?.)*?)\\3'), + + // build pseudoclass string + pseudoclass = '((?:' + + // an+b parameters or quoted string + pseudoparms + '|' + quotedvalue + '|' + + // id, class, pseudo-class selector + prefixes + '|' + encoding + '+|' + + // nested HTML attribute selector + '\\[' + attributes + '\\]|' + + // nested pseudo-class selector + '\\(.+\\)|' + whitespace + '|' + + // nested pseudos/separators + ',)+)', + + // placeholder for extensions + extensions = '.+', + + // CSS3: syntax scanner and + // one pass validation only + // using regular expression + standardValidator = + // discard start + '(?=[\\x20\\t\\n\\r\\f]*[^>+~(){}<>])' + + // open match group + '(' + + //universal selector + '\\*' + + // id/class/tag/pseudo-class identifier + '|(?:' + prefixes + identifier + ')' + + // combinator selector + '|' + combinators + + // HTML attribute selector + '|\\[' + attributes + '\\]' + + // pseudo-classes parameters + '|\\(' + pseudoclass + '\\)' + + // dom properties selector (extension) + '|\\{' + extensions + '\\}' + + // selector group separator (comma) + '|(?:,|' + whitespace + ')' + + // close match group + ')+', + + // validator for complex selectors in ':not()' pseudo-classes + extendedValidator = standardValidator.replace(pseudoclass, '.*'), + + // validator for standard selectors as default + reValidator = new RegExp(standardValidator, 'g'), + + // whitespace is any combination of these 5 character [\x20\t\n\r\f] + // http://www.w3.org/TR/css3-selectors/#selector-syntax + reTrimSpaces = new RegExp('^' + + whitespace + '|' + whitespace + '$', 'g'), + + // only allow simple selectors nested in ':not()' pseudo-classes + reSimpleNot = new RegExp('^(' + + '(?!:not)' + + '(' + prefixes + + '|' + identifier + + '|\\([^()]*\\))+' + + '|\\[' + attributes + '\\]' + + ')$'), + + // split comma groups, exclude commas from + // quotes '' "" and from brackets () [] {} + reSplitGroup = new RegExp('(' + + '[^,\\\\()[\\]]+' + + '|' + skipsquare + + '|' + skipround + + '|' + skipcurly + + '|\\\\.' + + ')+', 'g'), + + // split last, right most, selector group token + reSplitToken = new RegExp('(' + + '\\[' + attributes + '\\]|' + + '\\(' + pseudoclass + '\\)|' + + '[^\\x20\\t\\r\\n\\f>+~]|\\\\.)+', 'g'), + + // for in excess whitespace removal + reWhiteSpace = /[\x20\t\n\r\f]+/g, + + reOptimizeSelector = new RegExp(identifier + '|^$'), + + /*----------------------------- FEATURE TESTING ----------------------------*/ + + // detect native methods + isNative = (function() { + var s = (doc.appendChild + '').replace(/appendChild/g, ''); + return function(object, method) { + var m = object && object[method] || false; + return m && typeof m != 'string' && + s == (m + '').replace(new RegExp(method, 'g'), ''); + }; + })(), + + // NATIVE_XXXXX true if method exist and is callable + // detect if DOM methods are native in browsers + NATIVE_FOCUS = isNative(doc, 'hasFocus'), + NATIVE_QSAPI = isNative(doc, 'querySelector'), + NATIVE_GEBID = isNative(doc, 'getElementById'), + NATIVE_GEBTN = isNative(root, 'getElementsByTagName'), + NATIVE_GEBCN = isNative(root, 'getElementsByClassName'), + + // detect native getAttribute/hasAttribute methods, + // frameworks extend these to elements, but it seems + // this does not work for XML namespaced attributes, + // used to check both getAttribute/hasAttribute in IE + NATIVE_GET_ATTRIBUTE = isNative(root, 'getAttribute'), + NATIVE_HAS_ATTRIBUTE = isNative(root, 'hasAttribute'), + + // check if slice() can convert nodelist to array + // see http://yura.thinkweb2.com/cft/ + NATIVE_SLICE_PROTO = + (function() { + var isBuggy = false, id = root.id; + root.id = 'length'; + try { + isBuggy = !!slice.call(doc.childNodes, 0)[0]; + } catch(e) { } + root.id = id; + return isBuggy; + })(), + + // supports the new traversal API + NATIVE_TRAVERSAL_API = + 'nextElementSibling' in root && 'previousElementSibling' in root, + + // BUGGY_XXXXX true if method is feature tested and has known bugs + // detect buggy gEBID + BUGGY_GEBID = NATIVE_GEBID ? + (function() { + var isBuggy = true, x = 'x' + String(+new Date), + a = doc.createElementNS ? 'a' : ''; + (a = doc.createElement(a)).name = x; + root.insertBefore(a, root.firstChild); + isBuggy = !!doc.getElementById(x); + root.removeChild(a); + return isBuggy; + })() : + true, + + // detect IE gEBTN comment nodes bug + BUGGY_GEBTN = NATIVE_GEBTN ? + (function() { + var div = doc.createElement('div'); + div.appendChild(doc.createComment('')); + return !!div.getElementsByTagName('*')[0]; + })() : + true, + + // detect Opera gEBCN second class and/or UTF8 bugs as well as Safari 3.2 + // caching class name results and not detecting when changed, + // tests are based on the jQuery selector test suite + BUGGY_GEBCN = NATIVE_GEBCN ? + (function() { + var isBuggy, div = doc.createElement('div'), test = '\u53f0\u5317'; + + // Opera tests + div.appendChild(doc.createElement('span')). + setAttribute('class', test + 'abc ' + test); + div.appendChild(doc.createElement('span')). + setAttribute('class', 'x'); + + isBuggy = !div.getElementsByClassName(test)[0]; + + // Safari test + div.lastChild.className = test; + return isBuggy || div.getElementsByClassName(test).length != 2; + })() : + true, + + // detect IE bug with dynamic attributes + BUGGY_GET_ATTRIBUTE = NATIVE_GET_ATTRIBUTE ? + (function() { + var input = doc.createElement('input'); + input.setAttribute('value', 5); + return input.defaultValue != 5; + })() : + true, + + // detect IE bug with non-standard boolean attributes + BUGGY_HAS_ATTRIBUTE = NATIVE_HAS_ATTRIBUTE ? + (function() { + var option = doc.createElement('option'); + option.setAttribute('selected', 'selected'); + return !option.hasAttribute('selected'); + })() : + true, + + // detect Safari bug with selected option elements + BUGGY_SELECTED = + (function() { + var select = doc.createElement('select'); + select.appendChild(doc.createElement('option')); + return !select.firstChild.selected; + })(), + + // initialized with the loading context + // and reset for each different context + BUGGY_QUIRKS_GEBCN, + BUGGY_QUIRKS_QSAPI, + + QUIRKS_MODE, + XML_DOCUMENT, + + // detect Opera browser + OPERA = /opera/i.test(string.call(global.opera)), + + // skip simpe selector optimizations for Opera >= 11 + OPERA_QSAPI = OPERA && parseFloat(opera.version()) >= 11, + + // check Seletor API implementations + RE_BUGGY_QSAPI = NATIVE_QSAPI ? + (function() { + var pattern = [ ], div = doc.createElement('div'), element, + + expect = function(selector, context, element, n) { + var result = false; + context.appendChild(element); + try { result = context.querySelectorAll(selector).length == n; } catch(e) { } + while (context.firstChild) { context.removeChild(context.firstChild); } + return result; + }; + + // ^= $= *= operators bugs whith empty values (Opera 10 / IE8) + element = doc.createElement('p'); + element.setAttribute('class', ''); + expect('[class^=""]', div, element, 1) && + pattern.push('[*^$]=[\\x20\\t\\n\\r\\f]*(?:""|' + "'')"); + + // :checked bug with option elements (Firefox 3.6.x) + // it wrongly includes 'selected' options elements + // HTML5 rules says selected options also match + element = doc.createElement('option'); + element.setAttribute('selected', 'selected'); + expect(':checked', div, element, 0) && + pattern.push(':checked'); + + // :enabled :disabled bugs with hidden fields (Firefox 3.5) + // http://www.w3.org/TR/html5/links.html#selector-enabled + // http://www.w3.org/TR/css3-selectors/#enableddisabled + // not supported by IE8 Query Selector + element = doc.createElement('input'); + element.setAttribute('type', 'hidden'); + expect(':enabled', div, element, 0) && + pattern.push(':enabled', ':disabled'); + + // :link bugs with hyperlinks matching (Firefox/Safari) + element = doc.createElement('link'); + element.setAttribute('href', 'x'); + expect(':link', div, element, 1) || + pattern.push(':link'); + + // avoid attribute selectors for IE QSA + if (BUGGY_HAS_ATTRIBUTE) { + // IE fails in reading: + // - original values for input/textarea + // - original boolean values for controls + pattern.push('\\[[\\x20\\t\\n\\r\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)'); + } + + return pattern.length ? + new RegExp(pattern.join('|')) : + { 'test': function() { return false; } }; + + })() : + true, + + // matches class selectors + RE_CLASS = new RegExp('(?:\\[[\\x20\\t\\n\\r\\f]*class\\b|\\.' + identifier + ')'), + + // matches simple id, tag & class selectors + RE_SIMPLE_SELECTOR = new RegExp( + !(BUGGY_GEBTN && BUGGY_GEBCN) ? !OPERA ? + '^(?:\\*|[.#]?-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^(?:\\*|#-?[_a-zA-Z]{1}' + encoding + '*)$' : + '^#?-?[_a-zA-Z]{1}' + encoding + '*$'), + + /*----------------------------- LOOKUP OBJECTS -----------------------------*/ + + LINK_NODES = { 'a': 1, 'A': 1, 'area': 1, 'AREA': 1, 'link': 1, 'LINK': 1 }, + + // boolean attributes should return attribute name instead of true/false + ATTR_BOOLEAN = { + 'checked': 1, 'disabled': 1, 'ismap': 1, + 'multiple': 1, 'readonly': 1, 'selected': 1 + }, + + // dynamic attributes that needs to be checked against original HTML value + ATTR_DEFAULT = { + 'value': 'defaultValue', + 'checked': 'defaultChecked', + 'selected': 'defaultSelected' + }, + + // attributes referencing URI data values need special treatment in IE + ATTR_URIDATA = { + 'action': 2, 'cite': 2, 'codebase': 2, 'data': 2, 'href': 2, + 'longdesc': 2, 'lowsrc': 2, 'src': 2, 'usemap': 2 + }, + + // HTML 5 draft specifications + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + HTML_TABLE = { + // class attribute must be treated case-insensitive in HTML quirks mode + // initialized by default to Standard Mode (case-sensitive), + // set dynamically by the attribute resolver + 'class': 0, + 'accept': 1, 'accept-charset': 1, 'align': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'checked': 1, 'clear': 1, 'codetype': 1, 'color': 1, + 'compact': 1, 'declare': 1, 'defer': 1, 'dir': 1, 'direction': 1, 'disabled': 1, + 'enctype': 1, 'face': 1, 'frame': 1, 'hreflang': 1, 'http-equiv': 1, 'lang': 1, + 'language': 1, 'link': 1, 'media': 1, 'method': 1, 'multiple': 1, 'nohref': 1, + 'noresize': 1, 'noshade': 1, 'nowrap': 1, 'readonly': 1, 'rel': 1, 'rev': 1, + 'rules': 1, 'scope': 1, 'scrolling': 1, 'selected': 1, 'shape': 1, 'target': 1, + 'text': 1, 'type': 1, 'valign': 1, 'valuetype': 1, 'vlink': 1 + }, + + // the following attributes must be treated case-insensitive in XHTML mode + // Niels Leenheer http://rakaz.nl/item/css_selector_bugs_case_sensitivity + XHTML_TABLE = { + 'accept': 1, 'accept-charset': 1, 'alink': 1, 'axis': 1, + 'bgcolor': 1, 'charset': 1, 'codetype': 1, 'color': 1, + 'enctype': 1, 'face': 1, 'hreflang': 1, 'http-equiv': 1, + 'lang': 1, 'language': 1, 'link': 1, 'media': 1, 'rel': 1, + 'rev': 1, 'target': 1, 'text': 1, 'type': 1, 'vlink': 1 + }, + + /*-------------------------- REGULAR EXPRESSIONS ---------------------------*/ + + // placeholder to add functionalities + Selectors = { + // as a simple example this will check + // for chars not in standard ascii table + // + // 'mySpecialSelector': { + // 'Expression': /\u0080-\uffff/, + // 'Callback': mySelectorCallback + // } + // + // 'mySelectorCallback' will be invoked + // only after passing all other standard + // checks and only if none of them worked + }, + + // attribute operators + Operators = { + '=': "n=='%m'", + '^=': "n.indexOf('%m')==0", + '*=': "n.indexOf('%m')>-1", + '|=': "(n+'-').indexOf('%m-')==0", + '~=': "(' '+n+' ').indexOf(' %m ')>-1", + '$=': "n.substr(n.length-'%m'.length)=='%m'" + }, + + // optimization expressions + Optimize = { + ID: new RegExp('^\\*?#(' + encoding + '+)|' + skipgroup), + TAG: new RegExp('^(' + encoding + '+)|' + skipgroup), + CLASS: new RegExp('^\\*?\\.(' + encoding + '+$)|' + skipgroup) + }, + + // precompiled Regular Expressions + Patterns = { + // structural pseudo-classes and child selectors + spseudos: /^\:(root|empty|(?:first|last|only)(?:-child|-of-type)|nth(?:-last)?(?:-child|-of-type)\(\s*(even|odd|(?:[-+]{0,1}\d*n\s*)?[-+]{0,1}\s*\d*)\s*\))?(.*)/i, + // uistates + dynamic + negation pseudo-classes + dpseudos: /^\:(link|visited|target|active|focus|hover|checked|disabled|enabled|selected|lang\(([-\w]{2,})\)|not\(([^()]*|.*)\))?(.*)/i, + // element attribute matcher + attribute: new RegExp('^\\[' + attrmatcher + '\\](.*)'), + // E > F + children: /^[\x20\t\n\r\f]*\>[\x20\t\n\r\f]*(.*)/, + // E + F + adjacent: /^[\x20\t\n\r\f]*\+[\x20\t\n\r\f]*(.*)/, + // E ~ F + relative: /^[\x20\t\n\r\f]*\~[\x20\t\n\r\f]*(.*)/, + // E F + ancestor: /^[\x20\t\n\r\f]+(.*)/, + // all + universal: /^\*(.*)/, + // id + id: new RegExp('^#(' + encoding + '+)(.*)'), + // tag + tagName: new RegExp('^(' + encoding + '+)(.*)'), + // class + className: new RegExp('^\\.(' + encoding + '+)(.*)') + }, + + /*------------------------------ UTIL METHODS ------------------------------*/ + + // concat elements to data + concatList = + function(data, elements) { + var i = -1, element; + if (!data.length && Array.slice) + return Array.slice(elements); + while ((element = elements[++i])) + data[data.length] = element; + return data; + }, + + // concat elements to data and callback + concatCall = + function(data, elements, callback) { + var i = -1, element; + while ((element = elements[++i])) { + if (false === callback(data[data.length] = element)) { break; } + } + return data; + }, + + // change context specific variables + switchContext = + function(from, force) { + var div, oldDoc = doc; + // save passed context + lastContext = from; + // set new context document + doc = from.ownerDocument || from; + if (force || oldDoc !== doc) { + // set document root + root = doc.documentElement; + // set host environment flags + XML_DOCUMENT = doc.createElement('DiV').nodeName == 'DiV'; + + // In quirks mode css class names are case insensitive. + // In standards mode they are case sensitive. See docs: + // https://developer.mozilla.org/en/Mozilla_Quirks_Mode_Behavior + // http://www.whatwg.org/specs/web-apps/current-work/#selectors + QUIRKS_MODE = !XML_DOCUMENT && + typeof doc.compatMode == 'string' ? + doc.compatMode.indexOf('CSS') < 0 : + (function() { + var style = doc.createElement('div').style; + return style && (style.width = 1) && style.width == '1px'; + })(); + + div = doc.createElement('div'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xXx'); + div.appendChild(doc.createElement('p')).setAttribute('class', 'xxx'); + + // GEBCN buggy in quirks mode, match count is: + // Firefox 3.0+ [xxx = 1, xXx = 1] + // Opera 10.63+ [xxx = 0, xXx = 2] + BUGGY_QUIRKS_GEBCN = + !XML_DOCUMENT && NATIVE_GEBCN && QUIRKS_MODE && + (div.getElementsByClassName('xxx').length != 2 || + div.getElementsByClassName('xXx').length != 2); + + // QSAPI buggy in quirks mode, match count is: + // At least Chrome 4+, Firefox 3.5+, Opera 10.x+, Safari 4+ [xxx = 1, xXx = 2] + // Safari 3.2 QSA doesn't work with mixedcase in quirksmode [xxx = 1, xXx = 0] + // https://bugs.webkit.org/show_bug.cgi?id=19047 + // must test the attribute selector '[class~=xxx]' + // before '.xXx' or the bug may not present itself + BUGGY_QUIRKS_QSAPI = + !XML_DOCUMENT && NATIVE_QSAPI && QUIRKS_MODE && + (div.querySelectorAll('[class~=xxx]').length != 2 || + div.querySelectorAll('.xXx').length != 2); + + Config.CACHING && Dom.setCache(true, doc); + } + }, + + /*------------------------------ DOM METHODS -------------------------------*/ + + // element by id (raw) + // @return reference or null + byIdRaw = + function(id, elements) { + var i = -1, element = null; + while ((element = elements[++i])) { + if (element.getAttribute('id') == id) { + break; + } + } + return element; + }, + + // element by id + // @return reference or null + _byId = !BUGGY_GEBID ? + function(id, from) { + id = id.replace(/\\([^\\]{1})/g, '$1'); + return from.getElementById && from.getElementById(id) || + byIdRaw(id, from.getElementsByTagName('*')); + } : + function(id, from) { + var element = null; + id = id.replace(/\\([^\\]{1})/g, '$1'); + if (XML_DOCUMENT || from.nodeType != 9) { + return byIdRaw(id, from.getElementsByTagName('*')); + } + if ((element = from.getElementById(id)) && + element.name == id && from.getElementsByName) { + return byIdRaw(id, from.getElementsByName(id)); + } + return element; + }, + + // publicly exposed byId + // @return reference or null + byId = + function(id, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byId(id, from); + }, + + // elements by tag (raw) + // @return array + byTagRaw = + function(tag, from) { + var any = tag == '*', element = from, elements = [ ], next = element.firstChild; + any || (tag = tag.toUpperCase()); + while ((element = next)) { + if (element.tagName > '@' && (any || element.tagName.toUpperCase() == tag)) { + elements[elements.length] = element; + } + if ((next = element.firstChild || element.nextSibling)) continue; + while (!next && (element = element.parentNode) && element !== from) { + next = element.nextSibling; + } + } + return elements; + }, + + // elements by tag + // @return array + _byTag = !BUGGY_GEBTN && NATIVE_SLICE_PROTO ? + function(tag, from) { + return XML_DOCUMENT || from.nodeType == 11 ? byTagRaw(tag, from) : + slice.call(from.getElementsByTagName(tag), 0); + } : + function(tag, from) { + var i = -1, j = i, data = [ ], + element, elements = from.getElementsByTagName(tag); + if (tag == '*') { + while ((element = elements[++i])) { + if (element.nodeName > '@') + data[++j] = element; + } + } else { + while ((element = elements[++i])) { + data[i] = element; + } + } + return data; + }, + + // publicly exposed byTag + // @return array + byTag = + function(tag, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byTag(tag, from); + }, + + // publicly exposed byName + // @return array + byName = + function(name, from) { + return select('[name="' + name.replace(/\\([^\\]{1})/g, '$1') + '"]', from); + }, + + // elements by class (raw) + // @return array + byClassRaw = + function(name, from) { + var i = -1, j = i, data = [ ], element, elements = _byTag('*', from), n; + name = ' ' + (QUIRKS_MODE ? name.toLowerCase() : name).replace(/\\([^\\]{1})/g, '$1') + ' '; + while ((element = elements[++i])) { + n = XML_DOCUMENT ? element.getAttribute('class') : element.className; + if (n && n.length && (' ' + (QUIRKS_MODE ? n.toLowerCase() : n). + replace(reWhiteSpace, ' ') + ' ').indexOf(name) > -1) { + data[++j] = element; + } + } + return data; + }, + + // elements by class + // @return array + _byClass = + function(name, from) { + return (BUGGY_GEBCN || BUGGY_QUIRKS_GEBCN || XML_DOCUMENT || !from.getElementsByClassName) ? + byClassRaw(name, from) : slice.call(from.getElementsByClassName(name.replace(/\\([^\\]{1})/g, '$1')), 0); + }, + + // publicly exposed byClass + // @return array + byClass = + function(name, from) { + from || (from = doc); + if (lastContext !== from) { switchContext(from); } + return _byClass(name, from); + }, + + // check element is descendant of container + // @return boolean + contains = 'compareDocumentPosition' in root ? + function(container, element) { + return (container.compareDocumentPosition(element) & 16) == 16; + } : 'contains' in root ? + function(container, element) { + return container !== element && container.contains(element); + } : + function(container, element) { + while ((element = element.parentNode)) { + if (element === container) return true; + } + return false; + }, + + // attribute value + // @return string + getAttribute = !BUGGY_GET_ATTRIBUTE ? + function(node, attribute) { + return node.getAttribute(attribute) || ''; + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (typeof node[attribute] == 'object') { + return node.attributes[attribute] && + node.attributes[attribute].value || ''; + } + return ( + // 'type' can only be read by using native getAttribute + attribute == 'type' ? node.getAttribute(attribute) || '' : + // specific URI data attributes (parameter 2 to fix IE bug) + ATTR_URIDATA[attribute] ? node.getAttribute(attribute, 2) || '' : + // boolean attributes should return name instead of true/false + ATTR_BOOLEAN[attribute] ? node.getAttribute(attribute) ? attribute : 'false' : + ((node = node.getAttributeNode(attribute)) && node.value) || ''); + }, + + // attribute presence + // @return boolean + hasAttribute = !BUGGY_HAS_ATTRIBUTE ? + function(node, attribute) { + return XML_DOCUMENT ? + !!node.getAttribute(attribute) : + node.hasAttribute(attribute); + } : + function(node, attribute) { + attribute = attribute.toLowerCase(); + if (ATTR_DEFAULT[attribute]) { + return !!node[ATTR_DEFAULT[attribute]]; + } + // read the attribute node + node = node.getAttributeNode(attribute); + return !!(node && node.specified); + }, + + // check node emptyness + // @return boolean + isEmpty = + function(node) { + node = node.firstChild; + while (node) { + if (node.nodeType == 3 || node.nodeName > '@') return false; + node = node.nextSibling; + } + return true; + }, + + // check if element matches the :link pseudo + // @return boolean + isLink = + function(element) { + return hasAttribute(element,'href') && LINK_NODES[element.nodeName]; + }, + + // child position by nodeType + // @return number + nthElement = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling'; + while ((element = element[succ])) { + if (element.nodeName > '@') ++count; + } + return count; + }, + + // child position by nodeName + // @return number + nthOfType = + function(element, last) { + var count = 1, succ = last ? 'nextSibling' : 'previousSibling', type = element.nodeName; + while ((element = element[succ])) { + if (element.nodeName == type) ++count; + } + return count; + }, + + /*------------------------------- DEBUGGING --------------------------------*/ + + // get/set (string/object) working modes + configure = + function(option) { + if (typeof option == 'string') { return Config[option]; } + if (typeof option != 'object') { return false; } + for (var i in option) { + Config[i] = !!option[i]; + if (i == 'SIMPLENOT') { + matchContexts = { }; + matchResolvers = { }; + selectContexts = { }; + selectResolvers = { }; + Config['USE_QSAPI'] = false; + } else if (i == 'USE_QSAPI') { + Config[i] = !!option[i] && NATIVE_QSAPI; + } + } + reValidator = new RegExp(Config.SIMPLENOT ? + standardValidator : extendedValidator, 'g'); + return true; + }, + + // control user notifications + emit = + function(message) { + if (Config.VERBOSITY) { throw new Error(message); } + if (global.console && global.console.log) { + global.console.log(message); + } + }, + + Config = { + + // used to enable/disable caching of result sets + CACHING: false, + + // by default do not add missing left/right context + // to selector string shortcuts like "+div" or "ul>" + // callable Dom.shortcuts method has to be available + SHORTCUTS: false, + + // by default disable complex selectors nested in + // ':not()' pseudo-classes, as for specifications + SIMPLENOT: true, + + // strict QSA match all non-unique IDs (false) + // speed & libs compat match unique ID (true) + UNIQUE_ID: true, + + // HTML5 handling for the ":checked" pseudo-class + USE_HTML5: true, + + // controls enabling the Query Selector API branch + USE_QSAPI: NATIVE_QSAPI, + + // controls the engine error/warning notifications + VERBOSITY: true + + }, + + /*---------------------------- COMPILER METHODS ----------------------------*/ + + // code string reused to build compiled functions + ACCEPT_NODE = 'r[r.length]=c[k];if(f&&false===f(c[k]))break main;else continue main;', + + // compile a comma separated group of selector + // @mode boolean true for select, false for match + // return a compiled function + compile = + function(selector, source, mode) { + + var parts = typeof selector == 'string' ? selector.match(reSplitGroup) : selector; + + // ensures that source is a string + typeof source == 'string' || (source = ''); + + if (parts.length == 1) { + source += compileSelector(parts[0], mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } else { + // for each selector in the group + var i = -1, seen = { }, token; + while ((token = parts[++i])) { + token = token.replace(reTrimSpaces, ''); + // avoid repeating the same token + // in comma separated group (p, p) + if (!seen[token] && (seen[token] = true)) { + source += compileSelector(token, mode ? ACCEPT_NODE : 'f&&f(k);return true;', mode); + } + } + } + + if (mode) { + // for select method + return new Function('c,s,r,d,h,g,f,v', + 'var N,n,x=0,k=-1,e;main:while((e=c[++k])){' + source + '}return r;'); + } else { + // for match method + return new Function('e,s,r,d,h,g,f,v', + 'var N,n,x=0,k=e;' + source + 'return false;'); + } + }, + + // allows to cache already visited nodes + FILTER = + 'var z=v[@]||(v[@]=[]),l=z.length-1;' + + 'while(l>=0&&z[l]!==e)--l;' + + 'if(l!==-1){break;}' + + 'z[z.length]=e;', + + // compile a CSS3 string selector into ad-hoc javascript matching function + // @return string (to be compiled) + compileSelector = + function(selector, source, mode) { + + var a, b, n, k = 0, expr, match, result, status, test, type; + + while (selector) { + + k++; + + // *** Universal selector + // * match all (empty block, do not remove) + if ((match = selector.match(Patterns.universal))) { + // do nothing, handled in the compiler where + // BUGGY_GEBTN return comment nodes (ex: IE) + expr = ''; + } + + // *** ID selector + // #Foo Id case sensitive + else if ((match = selector.match(Patterns.id))) { + // document can contain conflicting elements (id/name) + // prototype selector unit need this method to recover bad HTML forms + source = 'if(' + (XML_DOCUMENT ? + 's.getAttribute(e,"id")' : + '(e.submit?s.getAttribute(e,"id"):e.id)') + + '=="' + match[1] + '"' + + '){' + source + '}'; + } + + // *** Type selector + // Foo Tag (case insensitive) + else if ((match = selector.match(Patterns.tagName))) { + // both tagName and nodeName properties may be upper/lower case + // depending on their creation NAMESPACE in createElementNS() + source = 'if(e.nodeName' + (XML_DOCUMENT ? + '=="' + match[1] + '"' : '.toUpperCase()' + + '=="' + match[1].toUpperCase() + '"') + + '){' + source + '}'; + } + + // *** Class selector + // .Foo Class (case sensitive) + else if ((match = selector.match(Patterns.className))) { + // W3C CSS3 specs: element whose "class" attribute has been assigned a + // list of whitespace-separated values, see section 6.4 Class selectors + // and notes at the bottom; explicitly non-normative in this specification. + source = 'if((n=' + (XML_DOCUMENT ? + 's.getAttribute(e,"class")' : 'e.className') + + ')&&n.length&&(" "+' + (QUIRKS_MODE ? 'n.toLowerCase()' : 'n') + + '.replace(' + reWhiteSpace + '," ")+" ").indexOf(" ' + + (QUIRKS_MODE ? match[1].toLowerCase() : match[1]) + ' ")>-1' + + '){' + source + '}'; + } + + // *** Attribute selector + // [attr] [attr=value] [attr="value"] [attr='value'] and !=, *=, ~=, |=, ^=, $= + // case sensitivity is treated differently depending on the document type (see map) + else if ((match = selector.match(Patterns.attribute))) { + + // xml namespaced attribute ? + expr = match[1].split(':'); + expr = expr.length == 2 ? expr[1] : expr[0] + ''; + + if (match[2] && !Operators[match[2]]) { + emit('Unsupported operator in attribute selectors "' + selector + '"'); + return ''; + } + + test = false; + type = 'false'; + + // replace Operators parameter if needed + if (match[2] && match[4] && (type = Operators[match[2]])) { + // case treatment depends on document + HTML_TABLE['class'] = QUIRKS_MODE ? 1 : 0; + // replace escaped values and HTML entities + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + match[4] = match[4].replace(/\\([0-9a-f]{2,2})/g, '\\x$1'); + test = (XML_DOCUMENT ? XHTML_TABLE : HTML_TABLE)[expr.toLowerCase()]; + type = type.replace(/\%m/g, test ? match[4].toLowerCase() : match[4]); + } else if (match[2] == '!=' || match[2] == '=') { + match[4] = match[4].replace(/(\x22|\x27)/g, '\\$1'); + type = 'n' + match[2] + '="' + match[4] + '"'; + } + + // build expression for has/getAttribute + expr = 'n=s.' + (match[2] ? 'get' : 'has') + + 'Attribute(e,"' + match[1] + '")' + + (test ? '.toLowerCase();' : ';'); + + source = expr + 'if(' + (match[2] ? type : 'n') + '){' + source + '}'; + } + + // *** Adjacent sibling combinator + // E + F (F adiacent sibling of E) + else if ((match = selector.match(Patterns.adjacent))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + 'var N' + k + '=e;while(e&&(e=e.previousElementSibling)){' + source + 'break;}e=N' + k + ';' : + 'var N' + k + '=e;while(e&&(e=e.previousSibling)){if(e.nodeName>"@"){' + source + 'break;}}e=N' + k + ';'; + } + + // *** General sibling combinator + // E ~ F (F relative sibling of E) + else if ((match = selector.match(Patterns.relative))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = NATIVE_TRAVERSAL_API ? + ('var N' + k + '=e;e=e.parentNode.firstElementChild;' + + 'while(e&&e!==N' + k + '){' + source + 'e=e.nextElementSibling;}e=N' + k + ';') : + ('var N' + k + '=e;e=e.parentNode.firstChild;' + + 'while(e&&e!==N' + k + '){if(e.nodeName>"@"){' + source + '}e=e.nextSibling;}e=N' + k + ';'); + } + + // *** Child combinator + // E > F (F children of E) + else if ((match = selector.match(Patterns.children))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + 'break;}e=N' + k + ';'; + } + + // *** Descendant combinator + // E F (E ancestor of F) + else if ((match = selector.match(Patterns.ancestor))) { + source = (mode ? '' : FILTER.replace(/@/g, k)) + source; + source = 'var N' + k + '=e;while(e&&e!==h&&e!==g&&(e=e.parentNode)){' + source + '}e=N' + k + ';'; + } + + // *** Structural pseudo-classes + // :root, :empty, + // :first-child, :last-child, :only-child, + // :first-of-type, :last-of-type, :only-of-type, + // :nth-child(), :nth-last-child(), :nth-of-type(), :nth-last-of-type() + else if ((match = selector.match(Patterns.spseudos)) && match[1]) { + + switch (match[1]) { + case 'root': + // element root of the document + if (match[3]) { + source = 'if(e===h||s.contains(h,e)){' + source + '}'; + } else { + source = 'if(e===h){' + source + '}'; + } + break; + + case 'empty': + // element that has no children + source = 'if(s.isEmpty(e)){' + source + '}'; + break; + + default: + if (match[1] && match[2]) { + if (match[2] == 'n') { + source = 'if(e!==h){' + source + '}'; + break; + } else if (match[2] == 'even') { + a = 2; + b = 0; + } else if (match[2] == 'odd') { + a = 2; + b = 1; + } else { + // assumes correct "an+b" format, "b" before "a" to keep "n" values + b = ((n = match[2].match(/(-?\d+)$/)) ? parseInt(n[1], 10) : 0); + a = ((n = match[2].match(/(-?\d*)n/i)) ? parseInt(n[1], 10) : 0); + if (n && n[1] == '-') a = -1; + } + + // build test expression out of structural pseudo (an+b) parameters + // see here: http://www.w3.org/TR/css3-selectors/#nth-child-pseudo + test = a > 1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n>=' + b + '&&(n-(' + b + '))%' + a + '==0' : a < -1 ? + (/last/i.test(match[1])) ? '(n-(' + b + '))%' + a + '==0' : + 'n<=' + b + '&&(n-(' + b + '))%' + a + '==0' : a=== 0 ? + 'n==' + b : + (/last/i.test(match[1])) ? + a == -1 ? 'n>=' + b : 'n<=' + b : + a == -1 ? 'n<=' + b : 'n>=' + b; + + // 4 cases: 1 (nth) x 4 (child, of-type, last-child, last-of-type) + source = + 'if(e!==h){' + + 'n=s[' + (/-of-type/i.test(match[1]) ? '"nthOfType"' : '"nthElement"') + ']' + + '(e,' + (/last/i.test(match[1]) ? 'true' : 'false') + ');' + + 'if(' + test + '){' + source + '}' + + '}'; + + } else { + // 6 cases: 3 (first, last, only) x 1 (child) x 2 (-of-type) + a = /first/i.test(match[1]) ? 'previous' : 'next'; + n = /only/i.test(match[1]) ? 'previous' : 'next'; + b = /first|last/i.test(match[1]); + + type = /-of-type/i.test(match[1]) ? '&&n.nodeName!=e.nodeName' : '&&n.nodeName<"@"'; + + source = 'if(e!==h){' + + ( 'n=e;while((n=n.' + a + 'Sibling)' + type + ');if(!n){' + (b ? source : + 'n=e;while((n=n.' + n + 'Sibling)' + type + ');if(!n){' + source + '}') + '}' ) + '}'; + } + break; + } + + } + + // *** negation, user action and target pseudo-classes + // *** UI element states and dynamic pseudo-classes + // CSS3 :not, :checked, :enabled, :disabled, :target + // CSS3 :active, :hover, :focus + // CSS3 :link, :visited + else if ((match = selector.match(Patterns.dpseudos)) && match[1]) { + + switch (match[1].match(/^\w+/)[0]) { + // CSS3 negation pseudo-class + case 'not': + // compile nested selectors, DO NOT pass the callback parameter + // SIMPLENOT allow disabling complex selectors nested + // in ':not()' pseudo-classes, breaks some test units + expr = match[3].replace(reTrimSpaces, ''); + + if (Config.SIMPLENOT && !reSimpleNot.test(expr)) { + // see above, log error but continue execution + emit('Negation pseudo-class only accepts simple selectors "' + selector + '"'); + return ''; + } else { + if ('compatMode' in doc) { + source = 'if(!' + compile(expr, '', false) + '(e,s,r,d,h,g)){' + source + '}'; + } else { + source = 'if(!s.match(e, "' + expr.replace(/\x22/g, '\\"') + '",g)){' + source +'}'; + } + } + break; + + // CSS3 UI element states + case 'checked': + // for radio buttons checkboxes (HTML4) and options (HTML5) + source = 'if((typeof e.form!=="undefined"&&(/^(?:radio|checkbox)$/i).test(e.type)&&e.checked)' + + (Config.USE_HTML5 ? '||(/^option$/i.test(e.nodeName)&&(e.selected||e.checked))' : '') + + '){' + source + '}'; + break; + case 'disabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===true){' + source + '}'; + break; + case 'enabled': + // does not consider hidden input fields + source = 'if(((typeof e.form!=="undefined"' + + (Config.USE_HTML5 ? '' : '&&!(/^hidden$/i).test(e.type)') + + ')||s.isLink(e))&&e.disabled===false){' + source + '}'; + break; + + // CSS3 lang pseudo-class + case 'lang': + test = ''; + if (match[2]) test = match[2].substr(0, 2) + '-'; + source = 'do{(n=e.lang||"").toLowerCase();' + + 'if((n==""&&h.lang=="' + match[2].toLowerCase() + '")||' + + '(n&&(n=="' + match[2].toLowerCase() + + '"||n.substr(0,3)=="' + test.toLowerCase() + '")))' + + '{' + source + 'break;}}while((e=e.parentNode)&&e!==g);'; + break; + + // CSS3 target pseudo-class + case 'target': + n = doc.location ? doc.location.hash : ''; + if (n) { + source = 'if(e.id=="' + n.slice(1) + '"){' + source + '}'; + } + break; + + // CSS3 dynamic pseudo-classes + case 'link': + source = 'if(s.isLink(e)&&!e.visited){' + source + '}'; + break; + case 'visited': + source = 'if(s.isLink(e)&&e.visited){' + source + '}'; + break; + + // CSS3 user action pseudo-classes IE & FF3 have native support + // these capabilities may be emulated by some event managers + case 'active': + if (XML_DOCUMENT) break; + source = 'if(e===d.activeElement){' + source + '}'; + break; + case 'hover': + if (XML_DOCUMENT) break; + source = 'if(e===d.hoverElement){' + source + '}'; + break; + case 'focus': + if (XML_DOCUMENT) break; + source = NATIVE_FOCUS ? + 'if(e===d.activeElement&&d.hasFocus()&&(e.type||e.href||!isNaN(e.tabIndex))){' + source + '}' : + 'if(e===d.activeElement&&(e.type||e.href)){' + source + '}'; + break; + + // CSS2 selected pseudo-classes, not part of current CSS3 drafts + // the 'selected' property is only available for option elements + case 'selected': + // fix Safari selectedIndex property bug + expr = BUGGY_SELECTED ? '||(n=e.parentNode)&&n.options[n.selectedIndex]===e' : ''; + source = 'if(/^option$/i.test(e.nodeName)&&(e.selected||e.checked' + expr + ')){' + source + '}'; + break; + + default: + break; + } + + } + + else { + + // this is where external extensions are + // invoked if expressions match selectors + expr = false; + status = false; + for (expr in Selectors) { + if ((match = selector.match(Selectors[expr].Expression)) && match[1]) { + result = Selectors[expr].Callback(match, source); + source = result.source; + status = result.status; + if (status) { break; } + } + } + + // if an extension fails to parse the selector + // it must return a false boolean in "status" + if (!status) { + // log error but continue execution, don't throw real exceptions + // because blocking following processes maybe is not a good idea + emit('Unknown pseudo-class selector "' + selector + '"'); + return ''; + } + + if (!expr) { + // see above, log error but continue execution + emit('Unknown token in selector "' + selector + '"'); + return ''; + } + + } + + // error if no matches found by the pattern scan + if (!match) { + emit('Invalid syntax in selector "' + selector + '"'); + return ''; + } + + // ensure "match" is not null or empty since + // we do not throw real DOMExceptions above + selector = match && match[match.length - 1]; + } + + return source; + }, + + /*----------------------------- QUERY METHODS ------------------------------*/ + + // match element with selector + // @return boolean + match = + function(element, selector, from, callback) { + + var parts; + + if (!(element && element.nodeName > '@')) { + emit('Invalid element argument'); + return false; + } else if (!selector || typeof selector != 'string') { + emit('Invalid selector argument'); + return false; + } else if (from && from.nodeType == 1 && !contains(from, element)) { + return false; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = element.ownerDocument)); + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, element, from)); + + if (lastMatcher != selector) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleMatch = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastMatcher = selector; + lastPartsMatch = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return false; + } + } else parts = lastPartsMatch; + + // compile matcher resolver if necessary + if (!matchResolvers[selector] || matchContexts[selector] !== from) { + matchResolvers[selector] = compile(isSingleMatch ? [selector] : parts, '', false); + matchContexts[selector] = from; + } + + return matchResolvers[selector](element, Snapshot, [ ], doc, root, from, callback, { }); + }, + + // select only the first element + // matching selector (document ordered) + first = + function(selector, from) { + return select(selector, from, function() { return false; })[0] || null; + }, + + // select elements matching selector + // using new Query Selector API + // or cross-browser client API + // @return array + select = + function(selector, from, callback) { + + var i, changed, element, elements, parts, token, original = selector; + + if (arguments.length === 0) { + emit('Not enough arguments'); + return [ ]; + } else if (typeof selector != 'string') { + return [ ]; + } else if (!(/[>+~*\w\u00a1-\uffff]/.test(selector))) { + emit('Invalid or illegal selector string'); + return [ ]; + } else if (from && !(/1|9|11/).test(from.nodeType)) { + emit('Invalid or illegal context element'); + return [ ]; + } else if (lastContext !== from) { + // reset context data when it changes + // and ensure context is set to a default + switchContext(from || (from = doc)); + } + + if (Config.CACHING && (elements = Dom.loadResults(original, from, doc, root))) { + return callback ? concatCall([ ], elements, callback) : elements; + } + + if (!OPERA_QSAPI && RE_SIMPLE_SELECTOR.test(selector)) { + switch (selector.charAt(0)) { + case '#': + if (Config.UNIQUE_ID && (element = _byId(selector.slice(1), from))) { + elements = [ element ]; + } else elements = [ ]; + break; + case '.': + elements = _byClass(selector.slice(1), from); + break; + default: + elements = _byTag(selector, from); + break; + } + } + + else if (!XML_DOCUMENT && Config.USE_QSAPI && + !(BUGGY_QUIRKS_QSAPI && RE_CLASS.test(selector)) && + !RE_BUGGY_QSAPI.test(selector)) { + try { + elements = from.querySelectorAll(selector); + } catch(e) { } + } + + if (elements) { + elements = callback ? concatCall([ ], elements, callback) : + NATIVE_SLICE_PROTO ? slice.call(elements) : concatList([ ], elements); + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + selector = selector.replace(reTrimSpaces, ''); + + Config.SHORTCUTS && (selector = NW.Dom.shortcuts(selector, from)); + + if ((changed = lastSelector != selector)) { + // process valid selector strings + if ((parts = selector.match(reValidator)) && parts[0] == selector) { + isSingleSelect = (parts = selector.match(reSplitGroup)).length < 2; + // save passed selector + lastSelector = selector; + lastPartsSelect = parts; + } else { + emit('The string "' + selector + '", is not a valid CSS selector'); + return [ ]; + } + } else parts = lastPartsSelect; + + // commas separators are treated sequentially to maintain order + if (from.nodeType == 11) { + + elements = from.childNodes; + + } else if (!XML_DOCUMENT && isSingleSelect) { + + if (changed) { + // get right most selector token + parts = selector.match(reSplitToken); + token = parts[parts.length - 1]; + + // only last slice before :not rules + lastSlice = token.split(':not')[0]; + + // position where token was found + lastPosition = selector.length - token.length; + } + + // ID optimization RTL, to reduce number of elements to visit + if (Config.UNIQUE_ID && (parts = lastSlice.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, from))) { + if (match(element, selector)) { + callback && callback(element); + elements = [ element ]; + } else elements = [ ]; + } + } + + // ID optimization LTR, to reduce selection context searches + else if (Config.UNIQUE_ID && (parts = selector.match(Optimize.ID)) && (token = parts[1])) { + if ((element = _byId(token, doc))) { + if ('#' + token == selector) { + callback && callback(element); + elements = [ element ]; + } else if (/[>+~]/.test(selector)) { + from = element.parentNode; + } else { + from = element; + } + } else elements = [ ]; + } + + if (elements) { + Config.CACHING && Dom.saveResults(original, from, doc, elements); + return elements; + } + + if (!NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + else if ((parts = lastSlice.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if ((parts = selector.match(Optimize.CLASS)) && (token = parts[1])) { + if ((elements = _byClass(token, from)).length === 0) { return [ ]; } + for (i = 0, els = [ ]; elements.length > i; ++i) { + els = concatList(els, elements[i].getElementsByTagName('*')); + } + elements = els; + if (reOptimizeSelector.test(selector.charAt(selector.indexOf(token) - 1))) { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, ''); + } else { + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace('.' + token, '*'); + } + } + + else if (NATIVE_GEBCN && (parts = lastSlice.match(Optimize.TAG)) && (token = parts[1])) { + if ((elements = _byTag(token, from)).length === 0) { return [ ]; } + selector = selector.slice(0, lastPosition) + selector.slice(lastPosition).replace(token, '*'); + } + + } + + if (!elements) { + elements = /^(?:applet|object)$/i.test(from.nodeName) ? from.childNodes : _byTag('*', from); + } + // end of prefiltering pass + + // compile selector resolver if necessary + if (!selectResolvers[selector] || selectContexts[selector] !== from) { + selectResolvers[selector] = compile(isSingleSelect ? [selector] : parts, '', true); + selectContexts[selector] = from; + } + + elements = selectResolvers[selector](elements, Snapshot, [ ], doc, root, from, callback, { }); + + Config.CACHING && Dom.saveResults(original, from, doc, elements); + + return elements; + }, + + /*-------------------------------- STORAGE ---------------------------------*/ + + // empty function handler + FN = function(x) { return x; }, + + // compiled match functions returning booleans + matchContexts = { }, + matchResolvers = { }, + + // compiled select functions returning collections + selectContexts = { }, + selectResolvers = { }, + + // used to pass methods to compiled functions + Snapshot = { + + // element indexing methods + nthElement: nthElement, + nthOfType: nthOfType, + + // element inspection methods + getAttribute: getAttribute, + hasAttribute: hasAttribute, + + // element selection methods + byClass: _byClass, + byName: byName, + byTag: _byTag, + byId: _byId, + + // helper/check methods + contains: contains, + isEmpty: isEmpty, + isLink: isLink, + + // selection/matching + select: select, + match: match + }, + + Tokens = { + prefixes: prefixes, + encoding: encoding, + operators: operators, + whitespace: whitespace, + identifier: identifier, + attributes: attributes, + combinators: combinators, + pseudoclass: pseudoclass, + pseudoparms: pseudoparms, + quotedvalue: quotedvalue + }; + + /*------------------------------- PUBLIC API -------------------------------*/ + + // code referenced by extensions + Dom.ACCEPT_NODE = ACCEPT_NODE; + + // log resolvers errors/warnings + Dom.emit = emit; + + // retrieve element by id attr + Dom.byId = byId; + + // retrieve elements by tag name + Dom.byTag = byTag; + + // retrieve elements by name attr + Dom.byName = byName; + + // retrieve elements by class name + Dom.byClass = byClass; + + // read the value of the attribute + // as was in the original HTML code + Dom.getAttribute = getAttribute; + + // check for the attribute presence + // as was in the original HTML code + Dom.hasAttribute = hasAttribute; + + // element match selector, return boolean true/false + Dom.match = match; + + // first element match only, return element or null + Dom.first = first; + + // elements matching selector, starting from element + Dom.select = select; + + // compile selector into ad-hoc javascript resolver + Dom.compile = compile; + + // check that two elements are ancestor/descendant + Dom.contains = contains; + + // handle selector engine configuration settings + Dom.configure = configure; + + // initialize caching for each document + Dom.setCache = FN; + + // load previously collected result set + Dom.loadResults = FN; + + // save previously collected result set + Dom.saveResults = FN; + + // handle missing context in selector strings + Dom.shortcuts = FN; + + // options enabing specific engine functionality + Dom.Config = Config; + + // pass methods references to compiled resolvers + Dom.Snapshot = Snapshot; + + // operators descriptor + // for attribute operators extensions + Dom.Operators = Operators; + + // selectors descriptor + // for pseudo-class selectors extensions + Dom.Selectors = Selectors; + + // export string patterns + Dom.Tokens = Tokens; + + // add or overwrite user defined operators + Dom.registerOperator = + function(symbol, resolver) { + Operators[symbol] || (Operators[symbol] = resolver); + }; + + // add selector patterns for user defined callbacks + Dom.registerSelector = + function(name, rexp, func) { + Selectors[name] || (Selectors[name] = { + Expression: rexp, + Callback: func + }); + }; + + /*---------------------------------- INIT ----------------------------------*/ + + // init context specific variables + switchContext(doc, true); + +}); diff --git a/node_modules/jsdom/node_modules/request/LICENSE b/node_modules/jsdom/node_modules/request/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/jsdom/node_modules/request/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/request/README.md b/node_modules/jsdom/node_modules/request/README.md new file mode 100644 index 0000000..d1f5c56 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/README.md @@ -0,0 +1,310 @@ +# Request -- Simplified HTTP request method + +## Install + +
    +  npm install request
    +
    + +Or from source: + +
    +  git clone git://github.com/mikeal/request.git 
    +  cd request
    +  npm link
    +
    + +## Super simple to use + +Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default. + +```javascript +var request = require('request'); +request('http://www.google.com', function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body) // Print the google web page. + } +}) +``` + +## Streaming + +You can stream any response to a file stream. + +```javascript +request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) +``` + +You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers. + +```javascript +fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json')) +``` + +Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers. + +```javascript +request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png')) +``` + +Now let's get fancy. + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + if (req.method === 'PUT') { + req.pipe(request.put('http://mysite.com/doodle.png')) + } else if (req.method === 'GET' || req.method === 'HEAD') { + request.get('http://mysite.com/doodle.png').pipe(resp) + } + } +}) +``` + +You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do: + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + var x = request('http://mysite.com/doodle.png') + req.pipe(x) + x.pipe(resp) + } +}) +``` + +And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :) + +```javascript +req.pipe(request('http://mysite.com/doodle.png')).pipe(resp) +``` + +Also, none of this new functionality conflicts with requests previous features, it just expands them. + +```javascript +var r = request.defaults({'proxy':'http://localproxy.com'}) + +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + r.get('http://google.com/doodle.png').pipe(resp) + } +}) +``` +You can still use intermediate proxies, the requests will still follow HTTP forwards, etc. + +## Forms + +`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API. + +Url encoded forms are simple + +```javascript +request.post('http://service.com/upload', {form:{key:'value'}}) +// or +request.post('http://service.com/upload').form({key:'value'}) +``` + +For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you. + +```javascript +var r = request.post('http://service.com/upload') +var form = r.form() +form.append('my_field', 'my_value') +form.append('my_buffer', new Buffer([1, 2, 3])) +form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')) +form.append('remote_file', request('http://google.com/doodle.png')) +``` + +## OAuth Signing + +```javascript +// Twitter OAuth +var qs = require('querystring') + , oauth = + { callback: 'http://mysite.com/callback/' + , consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + } + , url = 'https://api.twitter.com/oauth/request_token' + ; +request.post({url:url, oauth:oauth}, function (e, r, body) { + // Assume by some stretch of magic you aquired the verifier + var access_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: access_token.oauth_token + , verifier: VERIFIER + , token_secret: access_token.oauth_token_secret + } + , url = 'https://api.twitter.com/oauth/access_token' + ; + request.post({url:url, oauth:oauth}, function (e, r, body) { + var perm_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: perm_token.oauth_token + , token_secret: perm_token.oauth_token_secret + } + , url = 'https://api.twitter.com/1/users/show.json?' + , params = + { screen_name: perm_token.screen_name + , user_id: perm_token.user_id + } + ; + url += qs.stringify(params) + request.get({url:url, oauth:oauth, json:true}, function (e, r, user) { + console.log(user) + }) + }) +}) +``` + + + +### request(options, callback) + +The first argument can be either a url or an options object. The only required option is uri, all others are optional. + +* `uri` || `url` - fully qualified uri or a parsed url object from url.parse() +* `qs` - object containing querystring values to be appended to the uri +* `method` - http method, defaults to GET +* `headers` - http headers, defaults to {} +* `body` - entity body for POST and PUT requests. Must be buffer or string. +* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request. +* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json. +* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below. +* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true. +* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false. +* `maxRedirects` - the maximum number of redirects to follow, defaults to 10. +* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer. +* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets. +* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. +* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request +* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri. +* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. +* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option. +* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section) +* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services) + + +The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer. + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. + +### request.put + +Same as request() but defaults to `method: "PUT"`. + +```javascript +request.put(url) +``` + +### request.post + +Same as request() but defaults to `method: "POST"`. + +```javascript +request.post(url) +``` + +### request.head + +Same as request() but defaults to `method: "HEAD"`. + +```javascript +request.head(url) +``` + +### request.del + +Same as request() but defaults to `method: "DELETE"`. + +```javascript +request.del(url) +``` + +### request.get + +Alias to normal request method for uniformity. + +```javascript +request.get(url) +``` +### request.cookie + +Function that creates a new cookie. + +```javascript +request.cookie('cookie_string_here') +``` +### request.jar + +Function that creates a new cookie jar. + +```javascript +request.jar() +``` + + +## Examples: + +```javascript + var request = require('request') + , rand = Math.floor(Math.random()*100000000).toString() + ; + request( + { method: 'PUT' + , uri: 'http://mikeal.iriscouch.com/testjs/' + rand + , multipart: + [ { 'content-type': 'application/json' + , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) + } + , { body: 'I am an attachment' } + ] + } + , function (error, response, body) { + if(response.statusCode == 201){ + console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand) + } else { + console.log('error: '+ response.statusCode) + console.log(body) + } + } + ) +``` +Cookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent). + +```javascript +var request = request.defaults({jar: false}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` + +If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option: + +```javascript +var j = request.jar() +var request = request.defaults({jar:j}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` +OR + +```javascript +var j = request.jar() +var cookie = request.cookie('your_cookie_here') +j.add(cookie) +request({url: 'http://www.google.com', jar: j}, function () { + request('http://images.google.com') +}) +``` diff --git a/node_modules/jsdom/node_modules/request/aws.js b/node_modules/jsdom/node_modules/request/aws.js new file mode 100644 index 0000000..4d8d950 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/aws.js @@ -0,0 +1,191 @@ + +/*! + * knox - auth + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , parse = require('url').parse + ; + +/** + * Valid keys. + */ + +var keys = + [ 'acl' + , 'location' + , 'logging' + , 'notification' + , 'partNumber' + , 'policy' + , 'requestPayment' + , 'torrent' + , 'uploadId' + , 'uploads' + , 'versionId' + , 'versioning' + , 'versions' + , 'website' + ] + +/** + * Return an "Authorization" header value with the given `options` + * in the form of "AWS :" + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.authorization = function(options){ + return 'AWS ' + options.key + ':' + exports.sign(options) +} + +/** + * Simple HMAC-SHA1 Wrapper + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.hmacSha1 = function(options){ + return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64') +} + +/** + * Create a base64 sha1 HMAC for `options`. + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.sign = function(options){ + options.message = exports.stringToSign(options) + return exports.hmacSha1(options) +} + +/** + * Create a base64 sha1 HMAC for `options`. + * + * Specifically to be used with S3 presigned URLs + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.signQuery = function(options){ + options.message = exports.queryStringToSign(options) + return exports.hmacSha1(options) +} + +/** + * Return a string for sign() with the given `options`. + * + * Spec: + * + * \n + * \n + * \n + * \n + * [headers\n] + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.stringToSign = function(options){ + var headers = options.amazonHeaders || '' + if (headers) headers += '\n' + var r = + [ options.verb + , options.md5 + , options.contentType + , options.date.toUTCString() + , headers + options.resource + ] + return r.join('\n') +} + +/** + * Return a string for sign() with the given `options`, but is meant exclusively + * for S3 presigned URLs + * + * Spec: + * + * \n + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.queryStringToSign = function(options){ + return 'GET\n\n\n' + options.date + '\n' + options.resource +}; + +/** + * Perform the following: + * + * - ignore non-amazon headers + * - lowercase fields + * - sort lexicographically + * - trim whitespace between ":" + * - join with newline + * + * @param {Object} headers + * @return {String} + * @api private + */ + +exports.canonicalizeHeaders = function(headers){ + var buf = [] + , fields = Object.keys(headers) + ; + for (var i = 0, len = fields.length; i < len; ++i) { + var field = fields[i] + , val = headers[field] + , field = field.toLowerCase() + ; + if (0 !== field.indexOf('x-amz')) continue + buf.push(field + ':' + val) + } + return buf.sort().join('\n') +}; + +/** + * Perform the following: + * + * - ignore non sub-resources + * - sort lexicographically + * + * @param {String} resource + * @return {String} + * @api private + */ + +exports.canonicalizeResource = function(resource){ + var url = parse(resource, true) + , path = url.pathname + , buf = [] + ; + + Object.keys(url.query).forEach(function(key){ + if (!~keys.indexOf(key)) return + var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]) + buf.push(key + val) + }) + + return path + (buf.length ? '?' + buf.sort().join('&') : '') +}; diff --git a/node_modules/jsdom/node_modules/request/forever.js b/node_modules/jsdom/node_modules/request/forever.js new file mode 100644 index 0000000..1e1d4b9 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/forever.js @@ -0,0 +1,103 @@ +module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL + +var util = require('util') + , Agent = require('http').Agent + , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent + +function ForeverAgent(options) { + var self = this + self.options = options || {} + self.requests = {} + self.sockets = {} + self.freeSockets = {} + self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets + self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets + self.on('free', function(socket, host, port) { + var name = host + ':' + port + if (self.requests[name] && self.requests[name].length) { + self.requests[name].shift().onSocket(socket) + } else if (self.sockets[name].length < self.minSockets) { + if (!self.freeSockets[name]) self.freeSockets[name] = [] + self.freeSockets[name].push(socket) + + // if an error happens while we don't use the socket anyway, meh, throw the socket away + function onIdleError() { + socket.destroy() + } + socket._onIdleError = onIdleError + socket.on('error', onIdleError) + } else { + // If there are no pending requests just destroy the + // socket and it will get removed from the pool. This + // gets us out of timeout issues and allows us to + // default to Connection:keep-alive. + socket.destroy() + } + }) + +} +util.inherits(ForeverAgent, Agent) + +ForeverAgent.defaultMinSockets = 5 + + +ForeverAgent.prototype.createConnection = net.createConnection +ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest +ForeverAgent.prototype.addRequest = function(req, host, port) { + var name = host + ':' + port + if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { + var idleSocket = this.freeSockets[name].pop() + idleSocket.removeListener('error', idleSocket._onIdleError) + delete idleSocket._onIdleError + req._reusedSocket = true + req.onSocket(idleSocket) + } else { + this.addRequestNoreuse(req, host, port) + } +} + +ForeverAgent.prototype.removeSocket = function(s, name, host, port) { + if (this.sockets[name]) { + var index = this.sockets[name].indexOf(s) + if (index !== -1) { + this.sockets[name].splice(index, 1) + } + } else if (this.sockets[name] && this.sockets[name].length === 0) { + // don't leak + delete this.sockets[name] + delete this.requests[name] + } + + if (this.freeSockets[name]) { + var index = this.freeSockets[name].indexOf(s) + if (index !== -1) { + this.freeSockets[name].splice(index, 1) + if (this.freeSockets[name].length === 0) { + delete this.freeSockets[name] + } + } + } + + if (this.requests[name] && this.requests[name].length) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(name, host, port).emit('free') + } +} + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + options.port = port + options.host = host + return tls.connect(options) +} diff --git a/node_modules/jsdom/node_modules/request/main.js b/node_modules/jsdom/node_modules/request/main.js new file mode 100644 index 0000000..27b470b --- /dev/null +++ b/node_modules/jsdom/node_modules/request/main.js @@ -0,0 +1,1123 @@ +// Copyright 2010-2012 Mikeal Rogers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var http = require('http') + , https = false + , tls = false + , url = require('url') + , util = require('util') + , stream = require('stream') + , qs = require('querystring') + , oauth = require('./oauth') + , uuid = require('./uuid') + , ForeverAgent = require('./forever') + , Cookie = require('./vendor/cookie') + , CookieJar = require('./vendor/cookie/jar') + , cookieJar = new CookieJar + , tunnel = require('./tunnel') + , aws = require('./aws') + + , mime = require('mime') + , FormData = require('form-data') + ; + +if (process.logging) { + var log = process.logging('request') +} + +try { + https = require('https') +} catch (e) {} + +try { + tls = require('tls') +} catch (e) {} + +function toBase64 (str) { + return (new Buffer(str || "", "ascii")).toString("base64") +} + +// Hacky fix for pre-0.4.4 https +if (https && !https.Agent) { + https.Agent = function (options) { + http.Agent.call(this, options) + } + util.inherits(https.Agent, http.Agent) + https.Agent.prototype._getConnection = function (host, port, cb) { + var s = tls.connect(port, host, this.options, function () { + // do other checks here? + if (cb) cb() + }) + return s + } +} + +function isReadStream (rs) { + if (rs.readable && rs.path && rs.mode) { + return true + } +} + +function copy (obj) { + var o = {} + Object.keys(obj).forEach(function (i) { + o[i] = obj[i] + }) + return o +} + +var isUrl = /^https?:/ + +var globalPool = {} + +function Request (options) { + stream.Stream.call(this) + this.readable = true + this.writable = true + + if (typeof options === 'string') { + options = {uri:options} + } + + var reserved = Object.keys(Request.prototype) + for (var i in options) { + if (reserved.indexOf(i) === -1) { + this[i] = options[i] + } else { + if (typeof options[i] === 'function') { + delete options[i] + } + } + } + options = copy(options) + + this.init(options) +} +util.inherits(Request, stream.Stream) +Request.prototype.init = function (options) { + var self = this + + if (!options) options = {} + if (process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG)) console.error('REQUEST', options) + if (!self.pool && self.pool !== false) self.pool = globalPool + self.dests = [] + self.__isRequestRequest = true + + // Protect against double callback + if (!self._callback && self.callback) { + self._callback = self.callback + self.callback = function () { + if (self._callbackCalled) return // Print a warning maybe? + self._callback.apply(self, arguments) + self._callbackCalled = true + } + self.on('error', self.callback.bind()) + self.on('complete', self.callback.bind(self, null)) + } + + if (self.url) { + // People use this property instead all the time so why not just support it. + self.uri = self.url + delete self.url + } + + if (!self.uri) { + // this will throw if unhandled but is handleable when in a redirect + return self.emit('error', new Error("options.uri is a required argument")) + } else { + if (typeof self.uri == "string") self.uri = url.parse(self.uri) + } + if (self.proxy) { + if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth } + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } + } + + if (!self.uri.host || !self.uri.pathname) { + // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar + // Detect and reject it as soon as possible + var faultyUri = url.format(self.uri) + var message = 'Invalid URI "' + faultyUri + '"' + if (Object.keys(options).length === 0) { + // No option ? This can be the sign of a redirect + // As this is a case where the user cannot do anything (he didn't call request directly with this URL) + // he should be warned that it can be caused by a redirection (can save some hair) + message += '. This can be caused by a crappy redirection.' + } + self.emit('error', new Error(message)) + return // This error was fatal + } + + self._redirectsFollowed = self._redirectsFollowed || 0 + self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 + self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true + self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false + if (self.followRedirect || self.followAllRedirects) + self.redirects = self.redirects || [] + + self.headers = self.headers ? copy(self.headers) : {} + + self.setHost = false + if (!self.headers.host) { + self.headers.host = self.uri.hostname + if (self.uri.port) { + if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && + !(self.uri.port === 443 && self.uri.protocol === 'https:') ) + self.headers.host += (':'+self.uri.port) + } + self.setHost = true + } + + self.jar(self._jar || options.jar) + + if (!self.uri.pathname) {self.uri.pathname = '/'} + if (!self.uri.port) { + if (self.uri.protocol == 'http:') {self.uri.port = 80} + else if (self.uri.protocol == 'https:') {self.uri.port = 443} + } + + if (self.proxy && !self.tunnel) { + self.port = self.proxy.port + self.host = self.proxy.hostname + } else { + self.port = self.uri.port + self.host = self.uri.hostname + } + + self.clientErrorHandler = function (error) { + if (self._aborted) return + + if (self.setHost) delete self.headers.host + if (self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } + self.start() + self.req.end() + return + } + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + self.emit('error', error) + } + + self._parserErrorHandler = function (error) { + if (this.res) { + if (this.res.request) { + this.res.request.emit('error', error) + } else { + this.res.emit('error', error) + } + } else { + this._httpMessage.emit('error', error) + } + } + + if (options.form) { + self.form(options.form) + } + + if (options.oauth) { + self.oauth(options.oauth) + } + + if (options.aws) { + self.aws(options.aws) + } + + if (self.uri.auth && !self.headers.authorization) { + self.headers.authorization = "Basic " + toBase64(self.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { + self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + + if (options.qs) self.qs(options.qs) + + if (self.uri.path) { + self.path = self.uri.path + } else { + self.path = self.uri.pathname + (self.uri.search || "") + } + + if (self.path.length === 0) self.path = '/' + + if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + + if (options.json) { + self.json(options.json) + } else if (options.multipart) { + self.boundary = uuid() + self.multipart(options.multipart) + } + + if (self.body) { + var length = 0 + if (!Buffer.isBuffer(self.body)) { + if (Array.isArray(self.body)) { + for (var i = 0; i < self.body.length; i++) { + length += self.body[i].length + } + } else { + self.body = new Buffer(self.body) + length = self.body.length + } + } else { + length = self.body.length + } + if (length) { + if(!self.headers['content-length'] && !self.headers['Content-Length']) + self.headers['content-length'] = length + } else { + throw new Error('Argument error, options.body.') + } + } + + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol + , defaultModules = {'http:':http, 'https:':https} + , httpModules = self.httpModules || {} + ; + self.httpModule = httpModules[protocol] || defaultModules[protocol] + + if (!self.httpModule) return this.emit('error', new Error("Invalid protocol")) + + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + if (options.agentClass) { + self.agentClass = options.agentClass + } else if (options.forever) { + self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL + } else { + self.agentClass = self.httpModule.Agent + } + } + + if (self.pool === false) { + self.agent = false + } else { + self.agent = self.agent || self.getAgent() + if (self.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.maxSockets + } + if (self.pool.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.pool.maxSockets + } + } + + self.once('pipe', function (src) { + if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.") + self.src = src + if (isReadStream(src)) { + if (!self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = mime.lookup(src.path) + } else { + if (src.headers) { + for (var i in src.headers) { + if (!self.headers[i]) { + self.headers[i] = src.headers[i] + } + } + } + if (self._json && !self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = 'application/json' + if (src.method && !self.method) { + self.method = src.method + } + } + + self.on('pipe', function () { + console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") + }) + }) + + process.nextTick(function () { + if (self._aborted) return + + if (self._form) { + self.setHeaders(self._form.getHeaders()) + self._form.pipe(self) + } + if (self.body) { + if (Array.isArray(self.body)) { + self.body.forEach(function (part) { + self.write(part) + }) + } else { + self.write(self.body) + } + self.end() + } else if (self.requestBodyStream) { + console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") + self.requestBodyStream.pipe(self) + } else if (!self.src) { + if (self.method !== 'GET' && typeof self.method !== 'undefined') { + self.headers['content-length'] = 0 + } + self.end() + } + self.ntick = true + }) +} + +// Must call this when following a redirect from https to http or vice versa +// Attempts to keep everything as identical as possible, but update the +// httpModule, Tunneling agent, and/or Forever Agent in use. +Request.prototype._updateProtocol = function () { + var self = this + var protocol = self.uri.protocol + + if (protocol === 'https:') { + // previously was doing http, now doing https + // if it's https, then we might need to tunnel now. + if (self.proxy) { + self.tunnel = true + var tunnelFn = self.proxy.protocol === 'http:' + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + var tunnelOptions = { proxy: { host: self.proxy.hostname + , post: +self.proxy.port + , proxyAuth: self.proxy.auth } + , ca: self.ca } + self.agent = tunnelFn(tunnelOptions) + return + } + + self.httpModule = https + switch (self.agentClass) { + case ForeverAgent: + self.agentClass = ForeverAgent.SSL + break + case http.Agent: + self.agentClass = https.Agent + break + default: + // nothing we can do. Just hope for the best. + return + } + + // if there's an agent, we need to get a new one. + if (self.agent) self.agent = self.getAgent() + + } else { + if (log) log('previously https, now http') + // previously was doing https, now doing http + // stop any tunneling. + if (self.tunnel) self.tunnel = false + self.httpModule = http + switch (self.agentClass) { + case ForeverAgent.SSL: + self.agentClass = ForeverAgent + break + case https.Agent: + self.agentClass = http.Agent + break + default: + // nothing we can do. just hope for the best + return + } + + // if there's an agent, then get a new one. + if (self.agent) { + self.agent = null + self.agent = self.getAgent() + } + } +} + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.httpModule.Agent) { + poolKey += Agent.name + } + + if (!this.httpModule.globalAgent) { + // node 0.4.x + options.host = this.host + options.port = this.port + if (poolKey) poolKey += ':' + poolKey += this.host + ':' + this.port + } + + // ca option is only relevant if proxy or destination are https + var proxy = this.proxy + if (typeof proxy === 'string') proxy = url.parse(proxy) + var caRelevant = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:' + if (options.ca && caRelevant) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // we're using a stored agent. Make sure it's protocol-specific + poolKey = this.uri.protocol + poolKey + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) +} + +Request.prototype.start = function () { + var self = this + + if (self._aborted) return + + self._started = true + self.method = self.method || 'GET' + self.href = self.uri.href + if (log) log('%method %href', self) + + if (self.src && self.src.stat && self.src.stat.size && !self.headers['content-length'] && !self.headers['Content-Length']) { + self.headers['content-length'] = self.src.stat.size + } + if (self._aws) { + self.aws(self._aws, true) + } + self.req = self.httpModule.request(self, function (response) { + if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) { + response.connection.once('error', self._parserErrorHandler) + } + if (self._aborted) return + if (self._paused) response.pause() + + self.response = response + response.request = self + response.toJSON = toJSON + + if (self.httpModule === https && + self.strictSSL && + !response.client.authorized) { + var sslErr = response.client.authorizationError + self.emit('error', new Error('SSL Error: '+ sslErr)) + return + } + + if (self.setHost) delete self.headers.host + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + + var addCookie = function (cookie) { + if (self._jar) self._jar.add(new Cookie(cookie)) + else cookieJar.add(new Cookie(cookie)) + } + + if (response.headers['set-cookie'] && (!self._disableCookies)) { + if (Array.isArray(response.headers['set-cookie'])) response.headers['set-cookie'].forEach(addCookie) + else addCookie(response.headers['set-cookie']) + } + + if (response.statusCode >= 300 && response.statusCode < 400 && + (self.followAllRedirects || + (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST' && self.method !== 'DELETE'))) && + response.headers.location) { + if (self._redirectsFollowed >= self.maxRedirects) { + self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+self.uri.href)) + return + } + self._redirectsFollowed += 1 + + if (!isUrl.test(response.headers.location)) { + response.headers.location = url.resolve(self.uri.href, response.headers.location) + } + + var uriPrev = self.uri + self.uri = url.parse(response.headers.location) + + // handle the case where we change protocol from https to http or vice versa + if (self.uri.protocol !== uriPrev.protocol) { + self._updateProtocol() + } + + self.redirects.push( + { statusCode : response.statusCode + , redirectUri: response.headers.location + } + ) + if (self.followAllRedirects) self.method = 'GET' + // self.method = 'GET' // Force all redirects to use GET || commented out fixes #215 + delete self.src + delete self.req + delete self.agent + delete self._started + delete self.body + delete self._form + if (self.headers) { + delete self.headers.host + delete self.headers['content-type'] + delete self.headers['content-length'] + } + if (log) log('Redirect to %uri', self) + self.init() + return // Ignore the rest of the response + } else { + self._redirectsFollowed = self._redirectsFollowed || 0 + // Be a good stream and emit end when the response is finished. + // Hack to emit end on close because of a core bug that never fires end + response.on('close', function () { + if (!self._ended) self.response.emit('end') + }) + + if (self.encoding) { + if (self.dests.length !== 0) { + console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") + } else { + response.setEncoding(self.encoding) + } + } + + self.dests.forEach(function (dest) { + self.pipeDest(dest) + }) + + response.on("data", function (chunk) { + self._destdata = true + self.emit("data", chunk) + }) + response.on("end", function (chunk) { + self._ended = true + self.emit("end", chunk) + }) + response.on("close", function () {self.emit("close")}) + + self.emit('response', response) + + if (self.callback) { + var buffer = [] + var bodyLen = 0 + self.on("data", function (chunk) { + buffer.push(chunk) + bodyLen += chunk.length + }) + self.on("end", function () { + if (self._aborted) return + + if (buffer.length && Buffer.isBuffer(buffer[0])) { + var body = new Buffer(bodyLen) + var i = 0 + buffer.forEach(function (chunk) { + chunk.copy(body, i, 0, chunk.length) + i += chunk.length + }) + if (self.encoding === null) { + response.body = body + } else { + response.body = body.toString(self.encoding) + } + } else if (buffer.length) { + response.body = buffer.join('') + } + + if (self._json) { + try { + response.body = JSON.parse(response.body) + } catch (e) {} + } + + self.emit('complete', response, response.body) + }) + } + } + }) + + if (self.timeout && !self.timeoutTimer) { + self.timeoutTimer = setTimeout(function () { + self.req.abort() + var e = new Error("ETIMEDOUT") + e.code = "ETIMEDOUT" + self.emit("error", e) + }, self.timeout) + + // Set additional timeout on socket - in case if remote + // server freeze after sending headers + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function () { + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } + } + + self.req.on('error', self.clientErrorHandler) + self.req.on('drain', function() { + self.emit('drain') + }) + self.on('end', function() { + if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler) + }) + self.emit('request', self.req) +} + +Request.prototype.abort = function () { + this._aborted = true + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + +Request.prototype.pipeDest = function (dest) { + var response = this.response + // Called after the response is received + if (dest.headers) { + dest.headers['content-type'] = response.headers['content-type'] + if (response.headers['content-length']) { + dest.headers['content-length'] = response.headers['content-length'] + } + } + if (dest.setHeader) { + for (var i in response.headers) { + dest.setHeader(i, response.headers[i]) + } + dest.statusCode = response.statusCode + } + if (this.pipefilter) this.pipefilter(response, dest) +} + +// Composable API +Request.prototype.setHeader = function (name, value, clobber) { + if (clobber === undefined) clobber = true + if (clobber || !this.headers.hasOwnProperty(name)) this.headers[name] = value + else this.headers[name] += ',' + value + return this +} +Request.prototype.setHeaders = function (headers) { + for (var i in headers) {this.setHeader(i, headers[i])} + return this +} +Request.prototype.qs = function (q, clobber) { + var base + if (!clobber && this.uri.query) base = qs.parse(this.uri.query) + else base = {} + + for (var i in q) { + base[i] = q[i] + } + + this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base)) + this.url = this.uri + + return this +} +Request.prototype.form = function (form) { + if (form) { + this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' + this.body = qs.stringify(form).toString('utf8') + return this + } + // create form-data object + this._form = new FormData() + return this._form +} +Request.prototype.multipart = function (multipart) { + var self = this + self.body = [] + + if (!self.headers['content-type']) { + self.headers['content-type'] = 'multipart/related; boundary=' + self.boundary + } else { + self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary + } + + if (!multipart.forEach) throw new Error('Argument error, options.multipart.') + + if (self.preambleCRLF) { + self.body.push(new Buffer('\r\n')) + } + + multipart.forEach(function (part) { + var body = part.body + if(body == null) throw Error('Body attribute missing in multipart.') + delete part.body + var preamble = '--' + self.boundary + '\r\n' + Object.keys(part).forEach(function (key) { + preamble += key + ': ' + part[key] + '\r\n' + }) + preamble += '\r\n' + self.body.push(new Buffer(preamble)) + self.body.push(new Buffer(body)) + self.body.push(new Buffer('\r\n')) + }) + self.body.push(new Buffer('--' + self.boundary + '--')) + return self +} +Request.prototype.json = function (val) { + this.setHeader('accept', 'application/json') + this._json = true + if (typeof val === 'boolean') { + if (typeof this.body === 'object') { + this.setHeader('content-type', 'application/json') + this.body = JSON.stringify(this.body) + } + } else { + this.setHeader('content-type', 'application/json') + this.body = JSON.stringify(val) + } + return this +} +function getHeader(name, headers) { + var result, re, match + Object.keys(headers).forEach(function (key) { + re = new RegExp(name, 'i') + match = key.match(re) + if (match) result = headers[key] + }) + return result +} +Request.prototype.aws = function (opts, now) { + if (!now) { + this._aws = opts + return this + } + var date = new Date() + this.setHeader('date', date.toUTCString()) + var auth = + { key: opts.key + , secret: opts.secret + , verb: this.method.toUpperCase() + , date: date + , contentType: getHeader('content-type', this.headers) || '' + , md5: getHeader('content-md5', this.headers) || '' + , amazonHeaders: aws.canonicalizeHeaders(this.headers) + } + if (opts.bucket && this.path) { + auth.resource = '/' + opts.bucket + this.path + } else if (opts.bucket && !this.path) { + auth.resource = '/' + opts.bucket + } else if (!opts.bucket && this.path) { + auth.resource = this.path + } else if (!opts.bucket && !this.path) { + auth.resource = '/' + } + auth.resource = aws.canonicalizeResource(auth.resource) + this.setHeader('authorization', aws.authorization(auth)) + + return this +} + +Request.prototype.oauth = function (_oauth) { + var form + if (this.headers['content-type'] && + this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) === + 'application/x-www-form-urlencoded' + ) { + form = qs.parse(this.body) + } + if (this.uri.query) { + form = qs.parse(this.uri.query) + } + if (!form) form = {} + var oa = {} + for (var i in form) oa[i] = form[i] + for (var i in _oauth) oa['oauth_'+i] = _oauth[i] + if (!oa.oauth_version) oa.oauth_version = '1.0' + if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( (new Date()).getTime() / 1000 ).toString() + if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') + + oa.oauth_signature_method = 'HMAC-SHA1' + + var consumer_secret = oa.oauth_consumer_secret + delete oa.oauth_consumer_secret + var token_secret = oa.oauth_token_secret + delete oa.oauth_token_secret + + var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname + var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret) + + // oa.oauth_signature = signature + for (var i in form) { + if ( i.slice(0, 'oauth_') in _oauth) { + // skip + } else { + delete oa['oauth_'+i] + if (i !== 'x_auth_mode') delete oa[i] + } + } + this.headers.Authorization = + 'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',') + this.headers.Authorization += ',oauth_signature="' + oauth.rfc3986(signature) + '"' + return this +} +Request.prototype.jar = function (jar) { + var cookies + + if (this._redirectsFollowed === 0) { + this.originalCookieHeader = this.headers.cookie + } + + if (jar === false) { + // disable cookies + cookies = false + this._disableCookies = true + } else if (jar) { + // fetch cookie from the user defined cookie jar + cookies = jar.get({ url: this.uri.href }) + } else { + // fetch cookie from the global cookie jar + cookies = cookieJar.get({ url: this.uri.href }) + } + + if (cookies && cookies.length) { + var cookieString = cookies.map(function (c) { + return c.name + "=" + c.value + }).join("; ") + + if (this.originalCookieHeader) { + // Don't overwrite existing Cookie header + this.headers.cookie = this.originalCookieHeader + '; ' + cookieString + } else { + this.headers.cookie = cookieString + } + } + this._jar = jar + return this +} + + +// Stream API +Request.prototype.pipe = function (dest, opts) { + if (this.response) { + if (this._destdata) { + throw new Error("You cannot pipe after data has been emitted from the response.") + } else if (this._ended) { + throw new Error("You cannot pipe after the response has been ended.") + } else { + stream.Stream.prototype.pipe.call(this, dest, opts) + this.pipeDest(dest) + return dest + } + } else { + this.dests.push(dest) + stream.Stream.prototype.pipe.call(this, dest, opts) + return dest + } +} +Request.prototype.write = function () { + if (!this._started) this.start() + return this.req.write.apply(this.req, arguments) +} +Request.prototype.end = function (chunk) { + if (chunk) this.write(chunk) + if (!this._started) this.start() + this.req.end() +} +Request.prototype.pause = function () { + if (!this.response) this._paused = true + else this.response.pause.apply(this.response, arguments) +} +Request.prototype.resume = function () { + if (!this.response) this._paused = false + else this.response.resume.apply(this.response, arguments) +} +Request.prototype.destroy = function () { + if (!this._ended) this.end() +} + +// organize params for post, put, head, del +function initParams(uri, options, callback) { + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + uri = options.uri + } + return { uri: uri, options: options, callback: callback } +} + +function request (uri, options, callback) { + if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.') + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + } + + if (callback) options.callback = callback + var r = new Request(options) + return r +} + +module.exports = request + +request.initParams = initParams + +request.defaults = function (options, requester) { + var def = function (method) { + var d = function (uri, opts, callback) { + var params = initParams(uri, opts, callback) + for (var i in options) { + if (params.options[i] === undefined) params.options[i] = options[i] + } + if(typeof requester === 'function') { + if(method === request) { + method = requester + } else { + params.options._requester = requester + } + } + return method(params.options, params.callback) + } + return d + } + var de = def(request) + de.get = def(request.get) + de.post = def(request.post) + de.put = def(request.put) + de.head = def(request.head) + de.del = def(request.del) + de.cookie = def(request.cookie) + de.jar = request.jar + return de +} + +request.forever = function (agentOptions, optionsArg) { + var options = {} + if (optionsArg) { + for (option in optionsArg) { + options[option] = optionsArg[option] + } + } + if (agentOptions) options.agentOptions = agentOptions + options.forever = true + return request.defaults(options) +} + +request.get = request +request.post = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'POST' + return request(params.uri || null, params.options, params.callback) +} +request.put = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'PUT' + return request(params.uri || null, params.options, params.callback) +} +request.head = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'HEAD' + if (params.options.body || + params.options.requestBodyStream || + (params.options.json && typeof params.options.json !== 'boolean') || + params.options.multipart) { + throw new Error("HTTP HEAD requests MUST NOT include a request body.") + } + return request(params.uri || null, params.options, params.callback) +} +request.del = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'DELETE' + if(typeof params.options._requester === 'function') { + request = params.options._requester + } + return request(params.uri || null, params.options, params.callback) +} +request.jar = function () { + return new CookieJar +} +request.cookie = function (str) { + if (str && str.uri) str = str.uri + if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") + return new Cookie(str) +} + +// Safe toJSON + +function getSafe (self, uuid) { + if (typeof self === 'object' || typeof self === 'function') var safe = {} + if (Array.isArray(self)) var safe = [] + + var recurse = [] + + Object.defineProperty(self, uuid, {}) + + var attrs = Object.keys(self).filter(function (i) { + if (i === uuid) return false + if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true + return !(Object.getOwnPropertyDescriptor(self[i], uuid)) + }) + + + for (var i=0;i $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/README.md b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/README.md new file mode 100644 index 0000000..039d942 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/README.md @@ -0,0 +1,970 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous flow control (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Flow Control + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + +
    +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Flow Control + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name). + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass and error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }], + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other flow control functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/async.min.js.gzip b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/async.min.js.gzip new file mode 100644 index 0000000..e1c3294 Binary files /dev/null and b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/async.min.js.gzip differ diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.css b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.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 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. + + +var pSlice = Array.prototype.slice; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = exports; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({message: message, actual: actual, expected: expected}) + +assert.AssertionError = function AssertionError (options) { + this.name = "AssertionError"; + this.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.ok); +}; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, "==", assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, "!=", assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, "deepEqual", assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key] )) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, "===", assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as determined by !==. +// assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, "!==", assert.notStrictEqual); + } +}; + +function _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
    ' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/dist/async.min.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/dist/async.min.js new file mode 100644 index 0000000..f89741e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/dist/async.min.js @@ -0,0 +1 @@ +/*global setTimeout: false, console: false */(function(){var a={};var b=this,c=b.async;typeof module!=="undefined"&&module.exports?module.exports=a:b.async=a,a.noConflict=function(){b.async=c;return a};var d=function(a,b){if(a.forEach)return a.forEach(b);for(var c=0;cd?1:0};d(null,e(b.sort(c),function(a){return a.value}))})},a.auto=function(a,b){b=b||function(){};var c=g(a);if(!c.length)return b(null);var e=[];var i=[];var j=function(a){i.unshift(a)};var k=function(a){for(var b=0;b b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + if(q.saturated && tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + if(q.empty && tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + hasher = hasher || function (x) { + return x; + }; + return function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else { + fn.apply(null, args.concat([function () { + memo[key] = arguments; + callback.apply(null, arguments); + }])); + } + }; + }; + +}()); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/nodelint.cfg b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/package.json b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/package.json new file mode 100644 index 0000000..e5646d7 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/package.json @@ -0,0 +1,41 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "main": "./index", + "author": { + "name": "Caolan McMahon" + }, + "version": "0.1.9", + "repository": { + "type": "git", + "url": "git://github.com/caolan/async.git" + }, + "bugs": { + "url": "http://github.com/caolan/async/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/caolan/async/raw/master/LICENSE" + } + ], + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "async@0.1.9", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "fd9b6aca66495fd0f7e97f86e71c7706ca9ae754" + }, + "_from": "async@0.1.9" +} diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/.swp b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/.swp new file mode 100644 index 0000000..ece9b6b Binary files /dev/null and b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/.swp differ diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/test-async.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/test-async.js new file mode 100644 index 0000000..8c2cebd --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/test-async.js @@ -0,0 +1,1367 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.same(results, [false, undefined, undefined, null]); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.same(results, [false, undefined, undefined, null]); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/test.html b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

    Async.js Test Suite

    + + + diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore new file mode 100644 index 0000000..aba34f0 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore @@ -0,0 +1,3 @@ +*.un~ +/node_modules +/test/tmp diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/License b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +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. diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md new file mode 100644 index 0000000..1a9999e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md @@ -0,0 +1,132 @@ +# combined-stream + +A stream that emits multiple other streams one after another. + +## Installation + +``` bash +npm install combined-stream +``` + +## Usage + +Here is a simple example that shows how you can use combined-stream to combine +two files into one: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +While the example above works great, it will pause all source streams until +they are needed. If you don't want that to happen, you can set `pauseStreams` +to `false`: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create({pauseStreams: false}); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +However, what if you don't have all the source streams yet, or you don't want +to allocate the resources (file descriptors, memory, etc.) for them right away? +Well, in that case you can simply provide a callback that supplies the stream +by calling a `next()` function: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(function(next) { + next(fs.createReadStream('file1.txt')); +}); +combinedStream.append(function(next) { + next(fs.createReadStream('file2.txt')); +}); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +## API + +### CombinedStream.create([options]) + +Returns a new combined stream object. Available options are: + +* `maxDataSize` +* `pauseStreams` + +The effect of those options is described below. + +### combinedStream.pauseStreams = true + +Whether to apply back pressure to the underlaying streams. If set to `false`, +the underlaying streams will never be paused. If set to `true`, the +underlaying streams will be paused right after being appended, as well as when +`delayedStream.pipe()` wants to throttle. + +### combinedStream.maxDataSize = 2 * 1024 * 1024 + +The maximum amount of bytes (or characters) to buffer for all source streams. +If this value is exceeded, `combinedStream` emits an `'error'` event. + +### combinedStream.dataSize = 0 + +The amount of bytes (or characters) currently buffered by `combinedStream`. + +### combinedStream.append(stream) + +Appends the given `stream` to the combinedStream object. If `pauseStreams` is +set to `true, this stream will also be paused right away. + +`streams` can also be a function that takes one parameter called `next`. `next` +is a function that must be invoked in order to provide the `next` stream, see +example above. + +Regardless of how the `stream` is appended, combined-stream always attaches an +`'error'` listener to it, so you don't have to do that manually. + +Special case: `stream` can also be a String or Buffer. + +### combinedStream.write(data) + +You should not call this, `combinedStream` takes care of piping the appended +streams into itself for you. + +### combinedStream.resume() + +Causes `combinedStream` to start drain the streams it manages. The function is +idempotent, and also emits a `'resume'` event each time which usually goes to +the stream that is currently being drained. + +### combinedStream.pause(); + +If `combinedStream.pauseStreams` is set to `false`, this does nothing. +Otherwise a `'pause'` event is emitted, this goes to the stream that is +currently being drained, so you can use it to apply back pressure. + +### combinedStream.end(); + +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes +all streams from the queue. + +### combinedStream.destroy(); + +Same as `combinedStream.end()`, except it emits a `'close'` event instead of +`'end'`. + +## License + +combined-stream is licensed under the MIT license. diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js new file mode 100644 index 0000000..03754e6 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js @@ -0,0 +1,183 @@ +var util = require('util'); +var Stream = require('stream').Stream; +var DelayedStream = require('delayed-stream'); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + stream.on('data', this._checkDataSize.bind(this)); + + stream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + var stream = this._streams.shift(); + + + if (!stream) { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)) + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore new file mode 100644 index 0000000..2fedb26 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore @@ -0,0 +1,2 @@ +*.un~ +/node_modules/* diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +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. diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md new file mode 100644 index 0000000..5cb5b35 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md @@ -0,0 +1,154 @@ +# delayed-stream + +Buffers events from a stream until you are ready to handle them. + +## Installation + +``` bash +npm install delayed-stream +``` + +## Usage + +The following example shows how to write a http echo server that delays its +response by 1000 ms. + +``` javascript +var DelayedStream = require('delayed-stream'); +var http = require('http'); + +http.createServer(function(req, res) { + var delayed = DelayedStream.create(req); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 1000); +}); +``` + +If you are not using `Stream#pipe`, you can also manually release the buffered +events by calling `delayedStream.resume()`: + +``` javascript +var delayed = DelayedStream.create(req); + +setTimeout(function() { + // Emit all buffered events and resume underlaying source + delayed.resume(); +}, 1000); +``` + +## Implementation + +In order to use this meta stream properly, here are a few things you should +know about the implementation. + +### Event Buffering / Proxying + +All events of the `source` stream are hijacked by overwriting the `source.emit` +method. Until node implements a catch-all event listener, this is the only way. + +However, delayed-stream still continues to emit all events it captures on the +`source`, regardless of whether you have released the delayed stream yet or +not. + +Upon creation, delayed-stream captures all `source` events and stores them in +an internal event buffer. Once `delayedStream.release()` is called, all +buffered events are emitted on the `delayedStream`, and the event buffer is +cleared. After that, delayed-stream merely acts as a proxy for the underlaying +source. + +### Error handling + +Error events on `source` are buffered / proxied just like any other events. +However, `delayedStream.create` attaches a no-op `'error'` listener to the +`source`. This way you only have to handle errors on the `delayedStream` +object, rather than in two places. + +### Buffer limits + +delayed-stream provides a `maxDataSize` property that can be used to limit +the amount of data being buffered. In order to protect you from bad `source` +streams that don't react to `source.pause()`, this feature is enabled by +default. + +## API + +### DelayedStream.create(source, [options]) + +Returns a new `delayedStream`. Available options are: + +* `pauseStream` +* `maxDataSize` + +The description for those properties can be found below. + +### delayedStream.source + +The `source` stream managed by this object. This is useful if you are +passing your `delayedStream` around, and you still want to access properties +on the `source` object. + +### delayedStream.pauseStream = true + +Whether to pause the underlaying `source` when calling +`DelayedStream.create()`. Modifying this property afterwards has no effect. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. You can also modify this property during runtime. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. + +### delayedStream.dataSize = 0 + +The amount of data buffered so far. + +### delayedStream.readable + +An ECMA5 getter that returns the value of `source.readable`. + +### delayedStream.resume() + +If the `delayedStream` has not been released so far, `delayedStream.release()` +is called. + +In either case, `source.resume()` is called. + +### delayedStream.pause() + +Calls `source.pause()`. + +### delayedStream.pipe(dest) + +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`. + +### delayedStream.release() + +Emits and clears all events that have been buffered up so far. This does not +resume the underlaying source, use `delayedStream.resume()` instead. + +## License + +delayed-stream is licensed under the MIT license. diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js new file mode 100644 index 0000000..7c10d48 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js @@ -0,0 +1,99 @@ +var Stream = require('stream').Stream; +var util = require('util'); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +DelayedStream.prototype.__defineGetter__('readable', function() { + return this.source.readable; +}); + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json new file mode 100644 index 0000000..d394b92 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json @@ -0,0 +1,38 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "delayed-stream", + "description": "Buffers events from a stream until you are ready to handle them.", + "version": "0.0.5", + "homepage": "https://github.com/felixge/node-delayed-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-delayed-stream.git" + }, + "main": "./lib/delayed_stream", + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "far": "0.0.1" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "delayed-stream@0.0.5", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "56f46a53506f656e1a549c63d8794c6cf8b6e1fc" + }, + "_from": "delayed-stream@0.0.5" +} diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js new file mode 100644 index 0000000..4d71b8a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js @@ -0,0 +1,6 @@ +var common = module.exports; + +common.DelayedStream = require('..'); +common.assert = require('assert'); +common.fake = require('fake'); +common.PORT = 49252; diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js new file mode 100644 index 0000000..9ecad5b --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var DelayedStream = common.DelayedStream; +var http = require('http'); + +var UPLOAD = new Buffer(10 * 1024 * 1024); + +var server = http.createServer(function(req, res) { + var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length}); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 10); +}); +server.listen(common.PORT, function() { + var request = http.request({ + method: 'POST', + port: common.PORT, + }); + + request.write(UPLOAD); + request.end(); + + request.on('response', function(res) { + var received = 0; + res + .on('data', function(chunk) { + received += chunk.length; + }) + .on('end', function() { + assert.equal(received, UPLOAD.length); + server.close(); + }); + }); +}); + + diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js new file mode 100644 index 0000000..6f417f3 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js @@ -0,0 +1,21 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testAutoPause() { + var source = new Stream(); + + fake.expect(source, 'pause', 1); + var delayedStream = DelayedStream.create(source); + fake.verify(); +})(); + +(function testDisableAutoPause() { + var source = new Stream(); + fake.expect(source, 'pause', 0); + + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + fake.verify(); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js new file mode 100644 index 0000000..b50c397 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js @@ -0,0 +1,14 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(source, 'pause'); + delayedStream.pause(); + fake.verify(); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js new file mode 100644 index 0000000..fc4047e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js @@ -0,0 +1,48 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // delayedStream must not emit until we resume + fake.expect(delayedStream, 'emit', 0); + + // but our original source must emit + var params = []; + source.on('foo', function(param) { + params.push(param); + }); + + source.emit('foo', 1); + source.emit('foo', 2); + + // Make sure delayedStream did not emit, and source did + assert.deepEqual(params, [1, 2]); + fake.verify(); + + // After resume, delayedStream must playback all events + fake + .stub(delayedStream, 'emit') + .times(Infinity) + .withArg(1, 'newListener'); + fake.expect(delayedStream, 'emit', ['foo', 1]); + fake.expect(delayedStream, 'emit', ['foo', 2]); + fake.expect(source, 'resume'); + + delayedStream.resume(); + fake.verify(); + + // Calling resume again will delegate to source + fake.expect(source, 'resume'); + delayedStream.resume(); + fake.verify(); + + // Emitting more events directly leads to them being emitted + fake.expect(delayedStream, 'emit', ['foo', 3]); + source.emit('foo', 3); + fake.verify(); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js new file mode 100644 index 0000000..a9d35e7 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js @@ -0,0 +1,15 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testHandleSourceErrors() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // We deal with this by attaching a no-op listener to 'error' on the source + // when creating a new DelayedStream. This way error events on the source + // won't throw. + source.emit('error', new Error('something went wrong')); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js new file mode 100644 index 0000000..7638a2b --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testMaxDataSize() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false}); + + source.emit('data', new Buffer(1024)); + + fake + .expect(delayedStream, 'emit') + .withArg(1, 'error'); + source.emit('data', new Buffer(1)); + fake.verify(); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js new file mode 100644 index 0000000..7d312ab --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testPipeReleases() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(delayedStream, 'resume'); + delayedStream.pipe(new Stream()); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js new file mode 100644 index 0000000..d436163 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testProxyReadableProperty() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + source.readable = fake.value('source.readable'); + assert.strictEqual(delayedStream.readable, source.readable); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json new file mode 100644 index 0000000..7bb0fcf --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "combined-stream", + "description": "A stream that emits multiple other streams one after another.", + "version": "0.0.3", + "homepage": "https://github.com/felixge/node-combined-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-combined-stream.git" + }, + "main": "./lib/combined_stream", + "engines": { + "node": "*" + }, + "dependencies": { + "delayed-stream": "0.0.5" + }, + "devDependencies": { + "far": "0.0.1" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "combined-stream@0.0.3", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "c41c9899277b587901bb6ce4bf458b94693afafa" + }, + "_from": "combined-stream@0.0.3" +} diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js new file mode 100644 index 0000000..aa9ab3a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js @@ -0,0 +1,12 @@ +var common = module.exports; + +var path = require('path'); +var root = path.join(__dirname, '..'); + +common.dir = { + fixture: root + '/test/fixture', + tmp: root + '/test/tmp', +}; + +common.CombinedStream = require(root); +common.assert = require('assert'); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt new file mode 100644 index 0000000..50e0218 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt @@ -0,0 +1,256 @@ +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt new file mode 100644 index 0000000..da1d821 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt @@ -0,0 +1,256 @@ +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js new file mode 100644 index 0000000..44ecaba --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js @@ -0,0 +1,27 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE1)); + }); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE2)); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js new file mode 100644 index 0000000..e3fbd18 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js @@ -0,0 +1,34 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; + +(function testDataSizeGetter() { + var combinedStream = CombinedStream.create(); + + assert.strictEqual(combinedStream.dataSize, 0); + + // Test one stream + combinedStream._streams.push({dataSize: 10}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 10); + + // Test two streams + combinedStream._streams.push({dataSize: 23}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test currentStream + combinedStream._currentStream = {dataSize: 20}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 53); + + // Test currentStream without dataSize + combinedStream._currentStream = {}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test stream function + combinedStream._streams.push(function() {}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js new file mode 100644 index 0000000..c678575 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var BUFFER = new Buffer('Bacon is delicious'); +var FILE2 = common.dir.fixture + '/file2.txt'; +var STRING = 'The € kicks the $\'s ass!'; + +var EXPECTED = + fs.readFileSync(FILE1) + + BUFFER + + fs.readFileSync(FILE2) + + STRING; +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(BUFFER); + combinedStream.append(fs.createReadStream(FILE2)); + combinedStream.append(function(next) { + next(STRING); + }); + + var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js new file mode 100644 index 0000000..263cfdf --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js @@ -0,0 +1,35 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.equal(stream2.dataSize, 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + console.error(GOT.length, EXPECTED.length); + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js new file mode 100644 index 0000000..25f47a4 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js @@ -0,0 +1,24 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var gotErr = null; + combinedStream.on('error', function(err) { + gotErr = err; + }); + + process.on('exit', function() { + assert.ok(gotErr); + assert.ok(gotErr.message.match(/bytes/)); + }); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js new file mode 100644 index 0000000..30a3a6f --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js @@ -0,0 +1,30 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.ok(stream2.dataSize > 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/package.json b/node_modules/jsdom/node_modules/request/node_modules/form-data/package.json new file mode 100644 index 0000000..1948a5e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/package.json @@ -0,0 +1,43 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "form-data", + "description": "A module to create readable `\"multipart/form-data\"` streams. Can be used to submit forms and file uploads to other web applications.", + "version": "0.0.3", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-form-data.git" + }, + "main": "./lib/form_data", + "engines": { + "node": "*" + }, + "dependencies": { + "combined-stream": "0.0.3", + "mime": "~1.2.2", + "async": "~0.1.9" + }, + "devDependencies": { + "fake": "0.2.1", + "far": "0.0.1", + "formidable": "1.0.2", + "request": "~2.9.203" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "form-data@0.0.3", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "6eea17b45790b42d779a1d581d1b3600fe0c7c0d" + }, + "_from": "form-data" +} diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/common.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/common.js new file mode 100644 index 0000000..8a26482 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/common.js @@ -0,0 +1,14 @@ +var common = module.exports; +var path = require('path'); + +var rootDir = path.join(__dirname, '..'); +common.dir = { + lib: rootDir + '/lib', + fixture: rootDir + '/test/fixture', + tmp: rootDir + '/test/tmp', +}; + +common.assert = require('assert'); +common.fake = require('fake'); + +common.port = 8432; diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/fixture/bacon.txt b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/fixture/bacon.txt new file mode 100644 index 0000000..9804bbd --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/fixture/bacon.txt @@ -0,0 +1 @@ +Bacon is delicious. diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg new file mode 100644 index 0000000..7cea4dd Binary files /dev/null and b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg differ diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js new file mode 100644 index 0000000..44d3b4d --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js @@ -0,0 +1,93 @@ +var common = require('../common'); +var assert = common.assert; +var FormData = require(common.dir.lib + '/form_data'); +var fake = require('fake').create(); +var fs = require('fs'); + +(function testEmptyForm() { + var form = new FormData(); + var callback = fake.callback(arguments.callee.name + '-getLength'); + var calls = fake.expectAnytime(callback, [null, 0]).calls; + + form.getLength(callback); + + // Make sure our response is async + assert.strictEqual(calls.length, 0); +})(); + +(function testUtf8String() { + var FIELD = 'my_field'; + var VALUE = 'May the € be with you'; + + var form = new FormData(); + form.append(FIELD, VALUE); + var callback = fake.callback(arguments.callee.name + '-getLength'); + + var expectedLength = + form._overheadLength + + Buffer.byteLength(VALUE) + + form._lastBoundary().length; + + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + +(function testBuffer() { + var FIELD = 'my_field'; + var VALUE = new Buffer(23); + + var form = new FormData(); + form.append(FIELD, VALUE); + var callback = fake.callback(arguments.callee.name + '-getLength'); + + var expectedLength = + form._overheadLength + + VALUE.length + + form._lastBoundary().length; + + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + + +(function testStringFileBufferFile() { + var fields = [ + { + name: 'my_field', + value: 'Test 123', + }, + { + name: 'my_image', + value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), + }, + { + name: 'my_buffer', + value: new Buffer('123'), + }, + { + name: 'my_txt', + value: fs.createReadStream(common.dir.fixture + '/bacon.txt'), + }, + ]; + + var form = new FormData(); + var expectedLength = 0; + + fields.forEach(function(field) { + form.append(field.name, field.value); + if (field.value.path) { + var stat = fs.statSync(field.value.path); + expectedLength += stat.size; + } else { + expectedLength += field.value.length; + } + }); + + expectedLength += form._overheadLength + form._lastBoundary().length; + + var callback = fake.callback(arguments.callee.name + '-getLength'); + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + + diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js new file mode 100644 index 0000000..6dc2fb2 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; + +var FormData = require(common.dir.lib + '/form_data'); + +(function testOneBoundaryPerForm() { + var form = new FormData(); + var boundary = form.getBoundary(); + + assert.equal(boundary, form.getBoundary()); + assert.equal(boundary.length, 50); +})(); + +(function testUniqueBoundaryPerForm() { + var formA = new FormData(); + var formB = new FormData(); + assert.notEqual(formA.getBoundary(), formB.getBoundary()); +})(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-http-response.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-http-response.js new file mode 100644 index 0000000..8e183fe --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-http-response.js @@ -0,0 +1,121 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS; +var server; + +var parsedUrl = parseUrl(remoteFile) + , options = { + method: 'get', + port: parsedUrl.port || 80, + path: parsedUrl.pathname, + host: parsedUrl.hostname + } + ; + +http.request(options, function(res) { + + FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'remote_file', value: res } + ]; + + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + server.listen(common.port, function() { + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + + }); + + +}).end(); + +server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(remoteFile)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-pipe.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-pipe.js new file mode 100644 index 0000000..acc39df --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-pipe.js @@ -0,0 +1,111 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(common.port, function() { + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + var request = http.request({ + method: 'post', + port: common.port, + path: '/upload', + headers: form.getHeaders() + }); + + form.pipe(request); + + request.on('response', function(res) { + server.close(); + }); +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-submit.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-submit.js new file mode 100644 index 0000000..c40e88f --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/integration/test-submit.js @@ -0,0 +1,107 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg') }, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + req.on('data', function(d) { + data += d; + }); + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + +server.listen(common.port, function() { + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/jsdom/node_modules/request/node_modules/form-data/test/run.js b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/form-data/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/LICENSE b/node_modules/jsdom/node_modules/request/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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. diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/README.md b/node_modules/jsdom/node_modules/request/node_modules/mime/README.md new file mode 100644 index 0000000..b90552a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/README.md @@ -0,0 +1,63 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/mime.js b/node_modules/jsdom/node_modules/request/node_modules/mime/mime.js new file mode 100644 index 0000000..1e00585 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/mime.js @@ -0,0 +1,104 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + return this.extensions[mimeType]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +} + +module.exports = mime; diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/package.json b/node_modules/jsdom/node_modules/request/node_modules/mime/package.json new file mode 100644 index 0000000..06e2ee5 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/package.json @@ -0,0 +1,42 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "git://github.com/broofa/node-mime.git", + "type": "git" + }, + "version": "1.2.7", + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "mime@1.2.7", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "_from": "mime" +} diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/test.js b/node_modules/jsdom/node_modules/request/node_modules/mime/test.js new file mode 100644 index 0000000..cbad034 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/test.js @@ -0,0 +1,55 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); +eq('text/plain', mime.lookup('.text.txt')); +eq('text/plain', mime.lookup('.txt')); +eq('text/plain', mime.lookup('txt')); +eq('application/octet-stream', mime.lookup('text.nope')); +eq('fallback', mime.lookup('text.fallback', 'fallback')); +eq('application/octet-stream', mime.lookup('constructor')); +eq('text/plain', mime.lookup('TEXT.TXT')); +eq('text/event-stream', mime.lookup('text/event-stream')); +eq('application/x-web-app-manifest+json', mime.lookup('text.webapp')); + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq(undefined, mime.extension('constructor')); + +// +// Test node types +// + +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +console.log('\nOK'); diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/types/mime.types b/node_modules/jsdom/node_modules/request/node_modules/mime/types/mime.types new file mode 100644 index 0000000..b90b165 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/types/mime.types @@ -0,0 +1,1588 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +application/x-conference nsc +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-opml opml +text/x-pascal p pas +text/x-nfo nfo +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/node_modules/jsdom/node_modules/request/node_modules/mime/types/node.types b/node_modules/jsdom/node_modules/request/node_modules/mime/types/node.types new file mode 100644 index 0000000..9097334 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/node_modules/mime/types/node.types @@ -0,0 +1,59 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: The FLAC lossless codec format +# Why: Streaming and serving FLAC audio +# Added by: jacobrask +audio/flac flac + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp diff --git a/node_modules/jsdom/node_modules/request/oauth.js b/node_modules/jsdom/node_modules/request/oauth.js new file mode 100644 index 0000000..e35bfa6 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/oauth.js @@ -0,0 +1,43 @@ +var crypto = require('crypto') + , qs = require('querystring') + ; + +function sha1 (key, body) { + return crypto.createHmac('sha1', key).update(body).digest('base64') +} + +function rfc3986 (str) { + return encodeURIComponent(str) + .replace(/!/g,'%21') + .replace(/\*/g,'%2A') + .replace(/\(/g,'%28') + .replace(/\)/g,'%29') + .replace(/'/g,'%27') + ; +} + +function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) { + // adapted from https://dev.twitter.com/docs/auth/oauth and + // https://dev.twitter.com/docs/auth/creating-signature + + var querystring = Object.keys(params).sort().map(function(key){ + // big WTF here with the escape + encoding but it's what twitter wants + return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key])) + }).join('%26') + + var base = [ + httpMethod ? httpMethod.toUpperCase() : 'GET', + rfc3986(base_uri), + querystring + ].join('&') + + var key = [ + consumer_secret, + token_secret || '' + ].map(rfc3986).join('&') + + return sha1(key, base) +} + +exports.hmacsign = hmacsign +exports.rfc3986 = rfc3986 diff --git a/node_modules/jsdom/node_modules/request/package.json b/node_modules/jsdom/node_modules/request/package.json new file mode 100644 index 0000000..0a48591 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/package.json @@ -0,0 +1,43 @@ +{ + "name": "request", + "description": "Simplified HTTP request client.", + "tags": [ + "http", + "simple", + "util", + "utility" + ], + "version": "2.12.0", + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com" + }, + "repository": { + "type": "git", + "url": "http://github.com/mikeal/request.git" + }, + "bugs": { + "url": "http://github.com/mikeal/request/issues" + }, + "engines": [ + "node >= 0.3.6" + ], + "main": "./main", + "dependencies": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + }, + "bundleDependencies": [ + "form-data", + "mime" + ], + "scripts": { + "test": "node tests/run.js" + }, + "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n
    \n  npm install request\n
    \n\nOr from source:\n\n
    \n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n
    \n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nUrl encoded forms are simple\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload')\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))\nform.append('remote_file', request('http://google.com/doodle.png'))\n```\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Assume by some stretch of magic you aquired the verifier\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: VERIFIER\n , token_secret: access_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n", + "_id": "request@2.12.0", + "dist": { + "shasum": "11f46f20b3d0f4848c6383991c80790af16c8e48" + }, + "_from": "request@2.x" +} diff --git a/node_modules/jsdom/node_modules/request/tests/googledoodle.png b/node_modules/jsdom/node_modules/request/tests/googledoodle.png new file mode 100644 index 0000000..f80c9c5 Binary files /dev/null and b/node_modules/jsdom/node_modules/request/tests/googledoodle.png differ diff --git a/node_modules/jsdom/node_modules/request/tests/run.js b/node_modules/jsdom/node_modules/request/tests/run.js new file mode 100644 index 0000000..538a65c --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/run.js @@ -0,0 +1,45 @@ +var spawn = require('child_process').spawn + , exitCode = 0 + ; + +var tests = [ + 'test-body.js' + , 'test-cookie.js' + , 'test-cookiejar.js' + , 'test-defaults.js' + , 'test-errors.js' + , 'test-form.js' + , 'test-follow-all-303.js' + , 'test-follow-all.js' + , 'test-headers.js' + , 'test-httpModule.js' + , 'test-https.js' + , 'test-https-strict.js' + , 'test-oauth.js' + , 'test-params.js' + , 'test-pipes.js' + , 'test-pool.js' + , 'test-protocol-changing-redirect.js' + , 'test-proxy.js' + , 'test-piped-redirect.js' + , 'test-qs.js' + , 'test-redirect.js' + , 'test-timeout.js' + , 'test-toJSON.js' + , 'test-tunnel.js' +] + +var next = function () { + if (tests.length === 0) process.exit(exitCode); + + var file = tests.shift() + console.log(file) + var proc = spawn('node', [ 'tests/' + file ]) + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + proc.on('exit', function (code) { + exitCode += code || 0 + next() + }) +} +next() diff --git a/node_modules/jsdom/node_modules/request/tests/server.js b/node_modules/jsdom/node_modules/request/tests/server.js new file mode 100644 index 0000000..b6eacba --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/server.js @@ -0,0 +1,90 @@ +var fs = require('fs') + , http = require('http') + , path = require('path') + , https = require('https') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + ; + +exports.createServer = function (port) { + port = port || 6767 + var s = http.createServer(function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'http://localhost:'+port + return s; +} + +exports.createSSLServer = function(port, opts) { + port = port || 16767 + + var options = { 'key' : path.join(__dirname, 'ssl', 'test.key') + , 'cert': path.join(__dirname, 'ssl', 'test.crt') + } + if (opts) { + for (var i in opts) options[i] = opts[i] + } + + for (var i in options) { + options[i] = fs.readFileSync(options[i]) + } + + var s = https.createServer(options, function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'https://localhost:'+port + return s; +} + +exports.createPostStream = function (text) { + var postStream = new stream.Stream(); + postStream.writeable = true; + postStream.readable = true; + setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0); + return postStream; +} +exports.createPostValidator = function (text, reqContentType) { + var l = function (req, resp) { + var r = ''; + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) { + var boundary = req.headers['content-type'].split('boundary=')[1]; + text = text.replace(/__BOUNDARY__/g, boundary); + } + if (r !== text) console.log(r, text); + assert.equal(r, text) + if (reqContentType) { + assert.ok(req.headers['content-type']) + assert.ok(~req.headers['content-type'].indexOf(reqContentType)) + } + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write('OK') + resp.end() + }) + } + return l; +} +exports.createGetResponse = function (text, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + resp.write(text) + resp.end() + } + return l; +} +exports.createChunkResponse = function (chunks, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + chunks.forEach(function (chunk) { + resp.write(chunk) + }) + resp.end() + } + return l; +} diff --git a/node_modules/jsdom/node_modules/request/tests/squid.conf b/node_modules/jsdom/node_modules/request/tests/squid.conf new file mode 100644 index 0000000..0d4a3b6 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/squid.conf @@ -0,0 +1,77 @@ +# +# Recommended minimum configuration: +# +acl manager proto cache_object +acl localhost src 127.0.0.1/32 ::1 +acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1 + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 10.0.0.0/8 # RFC1918 possible internal network +acl localnet src 172.16.0.0/12 # RFC1918 possible internal network +acl localnet src 192.168.0.0/16 # RFC1918 possible internal network +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT + +# +# Recommended minimum Access Permission configuration: +# +# Only allow cachemgr access from localhost +http_access allow manager localhost +http_access deny manager + +# Deny requests to certain unsafe ports +http_access deny !Safe_ports + +# Deny CONNECT to other than secure SSL ports +#http_access deny CONNECT !SSL_ports + +# We strongly recommend the following be uncommented to protect innocent +# web applications running on the proxy server who think the only +# one who can access services on "localhost" is a local user +#http_access deny to_localhost + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# + +# Example rule allowing access from your local networks. +# Adapt localnet in the ACL section to list your (internal) IP networks +# from where browsing should be allowed +http_access allow localnet +http_access allow localhost + +# And finally deny all other access to this proxy +http_access deny all + +# Squid normally listens to port 3128 +http_port 3128 + +# We recommend you to use at least the following line. +hierarchy_stoplist cgi-bin ? + +# Uncomment and adjust the following to add a disk cache directory. +#cache_dir ufs /usr/local/var/cache 100 16 256 + +# Leave coredumps in the first cache dir +coredump_dir /usr/local/var/cache + +# Add any of your own refresh_pattern entries above these. +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern . 0 20% 4320 diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.cnf b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.cnf new file mode 100644 index 0000000..425a889 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.cnf @@ -0,0 +1,20 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no +output_password = password + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = request Certificate Authority +CN = requestCA +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.crl b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.crl new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.crt b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.crt new file mode 100644 index 0000000..b4524e4 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvTCCAiYCCQDn+P/MSbDsWjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGiMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxJjAkBgNVBAsTHXJlcXVlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MRIwEAYDVQQDEwlyZXF1ZXN0Q0ExJjAkBgkqhkiG9w0BCQEWF21pa2VhbEBtaWtl +YWxyb2dlcnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t9pQUAK4 +5XJYTI6NrF0n3G2HZsfN+rPYSVzzL8SuVyb1tHXos+vbPm3NKI4E8X1yVAXU8CjJ +5SqXnp4DAypAhaseho81cbhk7LXUhFz78OvAa+OD+xTAEAnNQ8tGUr4VGyplEjfD +xsBVuqV2j8GPNTftr+drOCFlqfAgMrBn4wIDAQABMA0GCSqGSIb3DQEBBQUAA4GB +ADVdTlVAL45R+PACNS7Gs4o81CwSclukBu4FJbxrkd4xGQmurgfRrYYKjtqiopQm +D7ysRamS3HMN9/VKq2T7r3z1PMHPAy7zM4uoXbbaTKwlnX4j/8pGPn8Ca3qHXYlo +88L/OOPc6Di7i7qckS3HFbXQCTiULtxWmy97oEuTwrAj +-----END CERTIFICATE----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.csr b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.csr new file mode 100644 index 0000000..e48c56e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.csr @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICBjCCAW8CAQAwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEmMCQGA1UECxMdcmVxdWVzdCBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAMTCXJlcXVlc3RDQTEmMCQGCSqG +SIb3DQEJARYXbWlrZWFsQG1pa2VhbHJvZ2Vycy5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBALu32lBQArjlclhMjo2sXSfcbYdmx836s9hJXPMvxK5XJvW0 +deiz69s+bc0ojgTxfXJUBdTwKMnlKpeengMDKkCFqx6GjzVxuGTstdSEXPvw68Br +44P7FMAQCc1Dy0ZSvhUbKmUSN8PGwFW6pXaPwY81N+2v52s4IWWp8CAysGfjAgMB +AAGgIzAhBgkqhkiG9w0BCQcxFBMScGFzc3dvcmQgY2hhbGxlbmdlMA0GCSqGSIb3 +DQEBBQUAA4GBAGJO7grHeVHXetjHEK8urIxdnvfB2qeZeObz4GPKIkqUurjr0rfj +bA3EK1kDMR5aeQWR8RunixdM16Q6Ry0lEdLVWkdSwRN9dmirIHT9cypqnD/FYOia +SdezZ0lUzXgmJIwRYRwB1KSMMocIf52ll/xC2bEGg7/ZAEuAyAgcZV3X +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.key b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.key new file mode 100644 index 0000000..a53e7f7 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C8B5887048377F02 + +nyD5ZH0Wup2uWsDvurq5mKDaDrf8lvNn9w0SH/ZkVnfR1/bkwqrFriqJWvZNUG+q +nS0iBYczsWLJnbub9a1zLOTENWUKVD5uqbC3aGHhnoUTNSa27DONgP8gHOn6JgR+ +GAKo01HCSTiVT4LjkwN337QKHnMP2fTzg+IoC/CigvMcq09hRLwU1/guq0GJKGwH +gTxYNuYmQC4Tjh8vdS4liF+Ve/P3qPR2CehZrIOkDT8PHJBGQJRo4xGUIB7Tpk38 +VCk+UZ0JCS2coY8VkY/9tqFJp/ZnnQQVmaNbdRqg7ECKL+bXnNo7yjzmazPZmPe3 +/ShbE0+CTt7LrjCaQAxWbeDzqfo1lQfgN1LulTm8MCXpQaJpv7v1VhIhQ7afjMYb +4thW/ypHPiYS2YJCAkAVlua9Oxzzh1qJoh8Df19iHtpd79Q77X/qf+1JvITlMu0U +gi7yEatmQcmYNws1mtTC1q2DXrO90c+NZ0LK/Alse6NRL/xiUdjug2iHeTf/idOR +Gg/5dSZbnnlj1E5zjSMDkzg6EHAFmHV4jYGSAFLEQgp4V3ZhMVoWZrvvSHgKV/Qh +FqrAK4INr1G2+/QTd09AIRzfy3/j6yD4A9iNaOsEf9Ua7Qh6RcALRCAZTWR5QtEf +dX+iSNJ4E85qXs0PqwkMDkoaxIJ+tmIRJY7y8oeylV8cfGAi8Soubt/i3SlR8IHC +uDMas/2OnwafK3N7ODeE1i7r7wkzQkSHaEz0TrF8XRnP25jAICCSLiMdAAjKfxVb +EvzsFSuAy3Jt6bU3hSLY9o4YVYKE+68ITMv9yNjvTsEiW+T+IbN34w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.srl b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.srl new file mode 100644 index 0000000..17128db --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/ca.srl @@ -0,0 +1 @@ +ADF62016AA40C9C3 diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.cnf b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.cnf new file mode 100644 index 0000000..cd1fd1e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.cnf @@ -0,0 +1,19 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = testing +CN = testing.request.mikealrogers.com +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.crt b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.crt new file mode 100644 index 0000000..efe96ce --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICejCCAeMCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGjMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxEDAOBgNVBAsTB3Rlc3RpbmcxKTAnBgNVBAMTIHRlc3RpbmcucmVx +dWVzdC5taWtlYWxyb2dlcnMuY29tMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlr +ZWFscm9nZXJzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDgVl0jMumvOpmM +20W5v9yhGgZj8hPhEQF/N7yCBVBn/rWGYm70IHC8T/pR5c0LkWc5gdnCJEvKWQjh +DBKxZD8FAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEABShRkNgFbgs4vUWW9R9deNJj +7HJoiTmvkmoOC7QzcYkjdgHbOxsSq3rBnwxsVjY9PAtPwBn0GRspOeG7KzKRgySB +kb22LyrCFKbEOfKO/+CJc80ioK9zEPVjGsFMyAB+ftYRqM+s/4cQlTg/m89l01wC +yapjN3RxZbInGhWR+jA= +-----END CERTIFICATE----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.csr b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.csr new file mode 100644 index 0000000..a8e7595 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBgjCCASwCAQAwgaMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEQMA4GA1UECxMHdGVzdGluZzEp +MCcGA1UEAxMgdGVzdGluZy5yZXF1ZXN0Lm1pa2VhbHJvZ2Vycy5jb20xJjAkBgkq +hkiG9w0BCQEWF21pa2VhbEBtaWtlYWxyb2dlcnMuY29tMFwwDQYJKoZIhvcNAQEB +BQADSwAwSAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAaAjMCEGCSqGSIb3DQEJBzEU +ExJwYXNzd29yZCBjaGFsbGVuZ2UwDQYJKoZIhvcNAQEFBQADQQBD3E5WekQzCEJw +7yOcqvtPYIxGaX8gRKkYfLPoj3pm3GF5SGqtJKhylKfi89szHXgktnQgzff9FN+A +HidVJ/3u +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.js b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.js new file mode 100644 index 0000000..05e21c1 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.js @@ -0,0 +1,28 @@ +var fs = require("fs") +var https = require("https") +var options = { key: fs.readFileSync("./server.key") + , cert: fs.readFileSync("./server.crt") } + +var server = https.createServer(options, function (req, res) { + res.writeHead(200) + res.end() + server.close() +}) +server.listen(1337) + +var ca = fs.readFileSync("./ca.crt") +var agent = new https.Agent({ host: "localhost", port: 1337, ca: ca }) + +https.request({ host: "localhost" + , method: "HEAD" + , port: 1337 + , headers: { host: "testing.request.mikealrogers.com" } + , agent: agent + , ca: [ ca ] + , path: "/" }, function (res) { + if (res.client.authorized) { + console.log("node test: OK") + } else { + throw new Error(res.client.authorizationError) + } +}).end() diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.key b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.key new file mode 100644 index 0000000..72d8698 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/ca/server.key @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAQJAK+r8ZM2sze8s7FRo/ApB +iRBtO9fCaIdJwbwJnXKo4RKwZDt1l2mm+fzZ+/QaQNjY1oTROkIIXmnwRvZWfYlW +gQIhAPKYsG+YSBN9o8Sdp1DMyZ/rUifKX3OE6q9tINkgajDVAiEA7Ltqh01+cnt0 +JEnud/8HHcuehUBLMofeg0G+gCnSbXECIQCqDvkXsWNNLnS/3lgsnvH0Baz4sbeJ +rjIpuVEeg8eM5QIgbu0+9JmOV6ybdmmiMV4yAncoF35R/iKGVHDZCAsQzDECIQDZ +0jGz22tlo5YMcYSqrdD3U4sds1pwiAaWFRbCunoUJw== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/npm-ca.crt b/node_modules/jsdom/node_modules/request/tests/ssl/npm-ca.crt new file mode 100644 index 0000000..fde2fe9 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/npm-ca.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x +IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w +bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y +MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV +BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj +YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA +aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE +OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz +Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl +y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC +l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv +yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl +ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op +-----END CERTIFICATE----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/test.crt b/node_modules/jsdom/node_modules/request/tests/ssl/test.crt new file mode 100644 index 0000000..b357f86 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQzCCAawCCQCO/XWtRFck1jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJU +SDEQMA4GA1UECBMHQmFuZ2tvazEOMAwGA1UEBxMFU2lsb20xGzAZBgNVBAoTElRo +ZSBSZXF1ZXN0IE1vZHVsZTEYMBYGA1UEAxMPcmVxdWVzdC5leGFtcGxlMB4XDTEx +MTIwMzAyMjkyM1oXDTIxMTEzMDAyMjkyM1owZjELMAkGA1UEBhMCVEgxEDAOBgNV +BAgTB0Jhbmdrb2sxDjAMBgNVBAcTBVNpbG9tMRswGQYDVQQKExJUaGUgUmVxdWVz +dCBNb2R1bGUxGDAWBgNVBAMTD3JlcXVlc3QuZXhhbXBsZTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwmctddZqlA48+NXs0yOy92DijcQV1jf87zMiYAIlNUto +wghVbTWgJU5r0pdKrD16AptnWJTzKanhItEX8XCCPgsNkq1afgTtJP7rNkwu3xcj +eIMkhJg/ay4ZnkbnhYdsii5VTU5prix6AqWRAhbkBgoA+iVyHyof8wvZyKBoFTMC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQB6BybMJbpeiABgihDfEVBcAjDoQ8gUMgwV +l4NulugfKTDmArqnR9aPd4ET5jX5dkMP4bwCHYsvrcYDeWEQy7x5WWuylOdKhua4 +L4cEi2uDCjqEErIG3cc1MCOk6Cl6Ld6tkIzQSf953qfdEACRytOeUqLNQcrXrqeE +c7U8F6MWLQ== +-----END CERTIFICATE----- diff --git a/node_modules/jsdom/node_modules/request/tests/ssl/test.key b/node_modules/jsdom/node_modules/request/tests/ssl/test.key new file mode 100644 index 0000000..b85810d --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/ssl/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDCZy111mqUDjz41ezTI7L3YOKNxBXWN/zvMyJgAiU1S2jCCFVt +NaAlTmvSl0qsPXoCm2dYlPMpqeEi0RfxcII+Cw2SrVp+BO0k/us2TC7fFyN4gySE +mD9rLhmeRueFh2yKLlVNTmmuLHoCpZECFuQGCgD6JXIfKh/zC9nIoGgVMwIDAQAB +AoGBALXFwfUf8vHTSmGlrdZS2AGFPvEtuvldyoxi9K5u8xmdFCvxnOcLsF2RsTHt +Mu5QYWhUpNJoG+IGLTPf7RJdj/kNtEs7xXqWy4jR36kt5z5MJzqiK+QIgiO9UFWZ +fjUb6oeDnTIJA9YFBdYi97MDuL89iU/UK3LkJN3hd4rciSbpAkEA+MCkowF5kSFb +rkOTBYBXZfiAG78itDXN6DXmqb9XYY+YBh3BiQM28oxCeQYyFy6pk/nstnd4TXk6 +V/ryA2g5NwJBAMgRKTY9KvxJWbESeMEFe2iBIV0c26/72Amgi7ZKUCLukLfD4tLF ++WSZdmTbbqI1079YtwaiOVfiLm45Q/3B0eUCQAaQ/0eWSGE+Yi8tdXoVszjr4GXb +G81qBi91DMu6U1It+jNfIba+MPsiHLcZJMVb4/oWBNukN7bD1nhwFWdlnu0CQQCf +Is9WHkdvz2RxbZDxb8verz/7kXXJQJhx5+rZf7jIYFxqX3yvTNv3wf2jcctJaWlZ +fVZwB193YSivcgt778xlAkEAprYUz3jczjF5r2hrgbizPzPDR94tM5BTO3ki2v3w +kbf+j2g7FNAx6kZiVN8XwfLc8xEeUGiPKwtq3ddPDFh17w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/jsdom/node_modules/request/tests/test-body.js b/node_modules/jsdom/node_modules/request/tests/test-body.js new file mode 100644 index 0000000..a624397 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-body.js @@ -0,0 +1,117 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetEncoding : + { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex')) + , encoding: 'hex' + , expectBody: "efa3bfcea9e29883" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + , testPutMultipartPreambleCRLF : + { resp: server.createPostValidator( + '\r\n--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , preambleCRLF: true + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/jsdom/node_modules/request/tests/test-cookie.js b/node_modules/jsdom/node_modules/request/tests/test-cookie.js new file mode 100644 index 0000000..6c6a7a7 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-cookie.js @@ -0,0 +1,29 @@ +var Cookie = require('../vendor/cookie') + , assert = require('assert'); + +var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT'; +var cookie = new Cookie(str); + +// test .toString() +assert.equal(cookie.toString(), str); + +// test .path +assert.equal(cookie.path, '/'); + +// test .httpOnly +assert.equal(cookie.httpOnly, true); + +// test .name +assert.equal(cookie.name, 'Sid'); + +// test .value +assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="'); + +// test .expires +assert.equal(cookie.expires instanceof Date, true); + +// test .path default +var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' }); +assert.equal(cookie.path, '/bar'); + +console.log('All tests passed'); diff --git a/node_modules/jsdom/node_modules/request/tests/test-cookiejar.js b/node_modules/jsdom/node_modules/request/tests/test-cookiejar.js new file mode 100644 index 0000000..76fcd71 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-cookiejar.js @@ -0,0 +1,90 @@ +var Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , assert = require('assert'); + +function expires(ms) { + return new Date(Date.now() + ms).toUTCString(); +} + +// test .get() expiration +(function() { + var jar = new Jar; + var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000)); + jar.add(cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 0); + }, 1000); + }, 5); +})(); + +// test .get() path support +(function() { + var jar = new Jar; + var a = new Cookie('sid=1234; path=/'); + var b = new Cookie('sid=1111; path=/foo/bar'); + var c = new Cookie('sid=2222; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + + // should remove the duplicates + assert.equal(jar.cookies.length, 2); + + // same name, same path, latter prevails + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], c); + + // same name, diff path, path specifity prevails, latter prevails + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], a); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=3333; path=/foo/bar'); + var c = new Cookie('pid=3333; path=/foo/bar'); + var d = new Cookie('sid=2222; path=/foo/'); + var e = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + jar.add(d); + jar.add(e); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 2); + assert.equal(cookies[0], b); + assert.equal(cookies[1], c); + + var cookies = jar.get({ url: 'http://foo.com/foo/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], d); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], e); +})(); + +setTimeout(function() { + console.log('All tests passed'); +}, 1200); diff --git a/node_modules/jsdom/node_modules/request/tests/test-defaults.js b/node_modules/jsdom/node_modules/request/tests/test-defaults.js new file mode 100644 index 0000000..ba09418 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-defaults.js @@ -0,0 +1,114 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +s.listen(s.port, function () { + var counter = 0; + s.on('/get', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'GET') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end('TESTING!'); + }); + + // test get(string, function) + request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){ + if (e) throw e; + assert.deepEqual("TESTING!", b); + counter += 1; + }); + + s.on('/post', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/post-body', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], 'application/json'); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) with body + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post-body', {json: true, body:{bar:"baz"}}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/del', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'DELETE') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test .del(string, function) + request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/head', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'HEAD') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test head.(object, function) + request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){ + if (e) throw e; + counter += 1; + }); + + s.on('/get_custom', function(req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers.x, 'y'); + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test custom request handler function + var defaultRequest = request.defaults({ + headers:{foo:"bar"} + , body: 'TESTING!' + }, function(uri, options, callback) { + var params = request.initParams(uri, options, callback); + options = params.options; + options.headers.x = 'y'; + + return request(params.uri, params.options, params.callback); + }); + + var msg = 'defaults test failed. head request should throw earlier'; + assert.throws(function() { + defaultRequest.head(s.url + '/get_custom', function(e, r, b) { + throw new Error(msg); + }); + counter+=1; + }, msg); + + defaultRequest.get(s.url + '/get_custom', function(e, r, b) { + if(e) throw e; + counter += 1; + console.log(counter.toString() + " tests passed."); + s.close(); + }); +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-errors.js b/node_modules/jsdom/node_modules/request/tests/test-errors.js new file mode 100644 index 0000000..1986a59 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-errors.js @@ -0,0 +1,37 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../main.js') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +try { + request(local, {multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/jsdom/node_modules/request/tests/test-follow-all-303.js b/node_modules/jsdom/node_modules/request/tests/test-follow-all-303.js new file mode 100644 index 0000000..3f2162d --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-follow-all-303.js @@ -0,0 +1,30 @@ +var request = require('../main'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + console.error(req.method, req.url); + requests ++; + + if (req.method === 'POST') { + console.error('send 303'); + res.setHeader('location', req.url); + res.statusCode = 303; + res.end('try again, i guess\n'); + } else { + console.error('send 200') + res.end('ok: ' + requests); + } +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 2'); + assert.equal(requests, 2); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/jsdom/node_modules/request/tests/test-follow-all.js b/node_modules/jsdom/node_modules/request/tests/test-follow-all.js new file mode 100644 index 0000000..b78745b --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-follow-all.js @@ -0,0 +1,35 @@ +var request = require('../main'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + requests ++; + + // redirect everything 3 times, no matter what. + var c = req.headers.cookie; + + if (!c) c = 0; + else c = +c.split('=')[1] || 0; + + if (c > 3) { + res.end('ok: '+requests); + return; + } + + res.setHeader('set-cookie', 'c=' + (c + 1)); + res.setHeader('location', req.url); + res.statusCode = 302; + res.end('try again, i guess\n'); +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 5'); + assert.equal(requests, 5); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/jsdom/node_modules/request/tests/test-form.js b/node_modules/jsdom/node_modules/request/tests/test-form.js new file mode 100644 index 0000000..aeefd31 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-form.js @@ -0,0 +1,79 @@ +var assert = require('assert') +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('../main.js'); +var fs = require('fs'); + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(__dirname + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(8080, function() { + + var req = request.post('http://localhost:8080/upload', function () { + server.close(); + }) + var form = req.form() + + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/jsdom/node_modules/request/tests/test-headers.js b/node_modules/jsdom/node_modules/request/tests/test-headers.js new file mode 100644 index 0000000..31fe3f4 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-headers.js @@ -0,0 +1,52 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , s = server.createServer() + +s.listen(s.port, function () { + var serverUri = 'http://localhost:' + s.port + , numTests = 0 + , numOutstandingTests = 0 + + function createTest(requestObj, serverAssertFn) { + var testNumber = numTests; + numTests += 1; + numOutstandingTests += 1; + s.on('/' + testNumber, function (req, res) { + serverAssertFn(req, res); + res.writeHead(200); + res.end(); + }); + requestObj.url = serverUri + '/' + testNumber + request(requestObj, function (err, res, body) { + assert.ok(!err) + assert.equal(res.statusCode, 200) + numOutstandingTests -= 1 + if (numOutstandingTests === 0) { + console.log(numTests + ' tests passed.') + s.close() + } + }) + } + + // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified + createTest({headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar') + }) + + // Issue #125: headers.cookie + cookie jar + var jar = new Jar() + jar.add(new Cookie('quux=baz')); + createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar; quux=baz') + }) + + // There should be no cookie header when neither headers.cookie nor a cookie jar is specified + createTest({}, function (req, res) { + assert.ok(!req.headers.cookie) + }) +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-httpModule.js b/node_modules/jsdom/node_modules/request/tests/test-httpModule.js new file mode 100644 index 0000000..1866de2 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-httpModule.js @@ -0,0 +1,94 @@ +var http = require('http') + , https = require('https') + , server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var faux_requests_made = {'http':0, 'https':0} +function wrap_request(name, module) { + // Just like the http or https module, but note when a request is made. + var wrapped = {} + Object.keys(module).forEach(function(key) { + var value = module[key]; + + if(key != 'request') + wrapped[key] = value; + else + wrapped[key] = function(options, callback) { + faux_requests_made[name] += 1 + return value.apply(this, arguments) + } + }) + + return wrapped; +} + + +var faux_http = wrap_request('http', http) + , faux_https = wrap_request('https', https) + , plain_server = server.createServer() + , https_server = server.createSSLServer() + + +plain_server.listen(plain_server.port, function() { + plain_server.on('/plain', function (req, res) { + res.writeHead(200) + res.end('plain') + }) + plain_server.on('/to_https', function (req, res) { + res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'}) + res.end() + }) + + https_server.listen(https_server.port, function() { + https_server.on('/https', function (req, res) { + res.writeHead(200) + res.end('https') + }) + https_server.on('/to_plain', function (req, res) { + res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'}) + res.end() + }) + + run_tests() + run_tests({}) + run_tests({'http:':faux_http}) + run_tests({'https:':faux_https}) + run_tests({'http:':faux_http, 'https:':faux_https}) + }) +}) + +function run_tests(httpModules) { + var to_https = 'http://localhost:'+plain_server.port+'/to_https' + var to_plain = 'https://localhost:'+https_server.port+'/to_plain' + + request(to_https, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to SSL worked') + assert.equal(body, 'https', 'Received HTTPS server body') + done() + }) + + request(to_plain, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to plaintext server worked') + assert.equal(body, 'plain', 'Received HTTPS server body') + done() + }) +} + + +var passed = 0; +function done() { + passed += 1 + var expected = 10 + + if(passed == expected) { + plain_server.close() + https_server.close() + + assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately') + assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately') + + console.log((expected+2) + ' tests passed.') + } +} diff --git a/node_modules/jsdom/node_modules/request/tests/test-https-strict.js b/node_modules/jsdom/node_modules/request/tests/test-https-strict.js new file mode 100644 index 0000000..470b68d --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-https-strict.js @@ -0,0 +1,97 @@ +// a test where we validate the siguature of the keys +// otherwise exactly the same as the ssl test + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key') + , cert: path.resolve(__dirname, 'ssl/ca/server.crt') } + , s = server.createSSLServer(null, opts) + , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt') + , ca = fs.readFileSync(caFile) + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.strictSSL = true + test.ca = ca + test.headers = { host: 'testing.request.mikealrogers.com' } + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-https.js b/node_modules/jsdom/node_modules/request/tests/test-https.js new file mode 100644 index 0000000..58e7db9 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-https.js @@ -0,0 +1,86 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + +var s = server.createSSLServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-oauth.js b/node_modules/jsdom/node_modules/request/tests/test-oauth.js new file mode 100644 index 0000000..72ca923 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-oauth.js @@ -0,0 +1,117 @@ +var hmacsign = require('../oauth').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../main') + ; + +function getsignature (r) { + var sign + r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var rsign = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +setTimeout(function () { + console.log(getsignature(rsign)) + assert.equal(reqsign, getsignature(rsign)) +}) + +var raccsign = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +setTimeout(function () { + console.log(getsignature(raccsign)) + assert.equal(accsign, getsignature(raccsign)) +}, 1) + +var rupsign = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) +setTimeout(function () { + console.log(getsignature(rupsign)) + assert.equal(upsign, getsignature(rupsign)) +}, 1) + + + + diff --git a/node_modules/jsdom/node_modules/request/tests/test-params.js b/node_modules/jsdom/node_modules/request/tests/test-params.js new file mode 100644 index 0000000..5ddb311 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-params.js @@ -0,0 +1,92 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + //test.uri = s.url + '/' + i + request(s.url + '/' + i, test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-piped-redirect.js b/node_modules/jsdom/node_modules/request/tests/test-piped-redirect.js new file mode 100644 index 0000000..25bf35d --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-piped-redirect.js @@ -0,0 +1,52 @@ +var http = require('http') + , assert = require('assert') + , request = require('../main.js') + ; + +var portOne = 8968 + , portTwo = 8969 + ; + + +// server one +var s1 = http.createServer(function (req, resp) +{ + if (req.url == '/original') + { + resp.writeHeader(302, {'location': '/redirected'}) + resp.end() + } + else if (req.url == '/redirected') + { + resp.writeHeader(200, {'content-type': 'text/plain'}) + resp.write('OK') + resp.end() + } + +}).listen(portOne); + + +// server two +var s2 = http.createServer(function (req, resp) +{ + + var x = request('http://localhost:'+portOne+'/original') + req.pipe(x) + x.pipe(resp) + +}).listen(portTwo, function() +{ + + var r = request('http://localhost:'+portTwo+'/original', function (err, res, body) { + + assert.equal(body, 'OK') + + s1.close() + s2.close() + + }); + + // it hangs, so wait a second :) + r.timeout = 1000; + +}); diff --git a/node_modules/jsdom/node_modules/request/tests/test-pipes.js b/node_modules/jsdom/node_modules/request/tests/test-pipes.js new file mode 100644 index 0000000..7162981 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-pipes.js @@ -0,0 +1,216 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + // Test pipeing to a request object with a json body + s.once('/push-json', server.createPostValidator("{\"foo\":\"bar\"}", "application/json")); + + var mybodydata = new stream.Stream(); + mybodydata.readable = true + + counter++ + var r2 = request.put({url:'http://localhost:3453/push-json',json:true}, function () { + check(); + }) + mybodydata.pipe(r2) + + mybodydata.emit('data', JSON.stringify({foo:"bar"})); + mybodydata.emit('end'); + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'application/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/png'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.png')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.png')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.png')), fs.readFileSync(path.join(__dirname, 'test.png'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.png')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + + s.on('/forward1', function (req, resp) { + resp.writeHead(302, {location:'/forward2'}) + resp.end() + }) + s.on('/forward2', function (req, resp) { + resp.writeHead('200', {'content-type':'image/png'}) + resp.write('d') + resp.end() + }) + + counter++ + var validateForward = new ValidationStream('d') + validateForward.on('end', check) + request.get('http://localhost:3453/forward1').pipe(validateForward) + + // Test pipe options + s.once('/opts', server.createGetResponse('opts response')); + + var optsStream = new stream.Stream(); + optsStream.writable = true + + var optsData = ''; + optsStream.write = function (buf) { + optsData += buf; + if (optsData === 'opts response') { + setTimeout(check, 10); + } + } + + optsStream.end = function () { + assert.fail('end called') + }; + + counter++ + request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false }) +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-pool.js b/node_modules/jsdom/node_modules/request/tests/test-pool.js new file mode 100644 index 0000000..1e7d578 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-pool.js @@ -0,0 +1,16 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200; + resp.end('asdf'); +}).listen(8080, function () { + request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) { + var agent = resp.request.agent; + assert.strictEqual(typeof agent, 'boolean'); + assert.strictEqual(agent, false); + s.close(); + }); +}); \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/request/tests/test-protocol-changing-redirect.js b/node_modules/jsdom/node_modules/request/tests/test-protocol-changing-redirect.js new file mode 100644 index 0000000..f74e196 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-protocol-changing-redirect.js @@ -0,0 +1,60 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var s = server.createServer() +var ss = server.createSSLServer() +var sUrl = 'http://localhost:' + s.port +var ssUrl = 'https://localhost:' + ss.port + +s.listen(s.port, bouncy(s, ssUrl)) +ss.listen(ss.port, bouncy(ss, sUrl)) + +var hits = {} +var expect = {} +var pending = 0 +function bouncy (s, server) { return function () { + + var redirs = { a: 'b' + , b: 'c' + , c: 'd' + , d: 'e' + , e: 'f' + , f: 'g' + , g: 'h' + , h: 'end' } + + var perm = true + Object.keys(redirs).forEach(function (p) { + var t = redirs[p] + + // switch type each time + var type = perm ? 301 : 302 + perm = !perm + s.on('/' + p, function (req, res) { + res.writeHead(type, { location: server + '/' + t }) + res.end() + }) + }) + + s.on('/end', function (req, res) { + var h = req.headers['x-test-key'] + hits[h] = true + pending -- + if (pending === 0) done() + }) +}} + +for (var i = 0; i < 5; i ++) { + pending ++ + var val = 'test_' + i + expect[val] = true + request({ url: (i % 2 ? sUrl : ssUrl) + '/a' + , headers: { 'x-test-key': val } }) +} + +function done () { + assert.deepEqual(hits, expect) + process.exit(0) +} diff --git a/node_modules/jsdom/node_modules/request/tests/test-proxy.js b/node_modules/jsdom/node_modules/request/tests/test-proxy.js new file mode 100644 index 0000000..647157c --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-qs.js b/node_modules/jsdom/node_modules/request/tests/test-qs.js new file mode 100644 index 0000000..1aac22b --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-qs.js @@ -0,0 +1,28 @@ +var request = request = require('../main.js') + , assert = require('assert') + ; + + +// Test adding a querystring +var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req1.path) +}, 1) + +// Test replacing a querystring value +var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req2.path) +}, 1) + +// Test appending a querystring value to the ones present in the uri +var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?x=y&q=search', req3.path) +}, 1) + +// Test leaving a querystring alone +var req4 = request.get({ uri: 'http://www.google.com?x=y'}) +setTimeout(function() { + assert.equal('/?x=y', req4.path) +}, 1) diff --git a/node_modules/jsdom/node_modules/request/tests/test-redirect.js b/node_modules/jsdom/node_modules/request/tests/test-redirect.js new file mode 100644 index 0000000..b84844a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-redirect.js @@ -0,0 +1,154 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + +var s = server.createServer() + +s.listen(s.port, function () { + var server = 'http://localhost:' + s.port; + var hits = {} + var passed = 0; + + bouncer(301, 'temp') + bouncer(302, 'perm') + bouncer(302, 'nope') + + function bouncer(code, label) { + var landing = label+'_landing'; + + s.on('/'+label, function (req, res) { + hits[label] = true; + res.writeHead(code, { + 'location':server + '/'+landing, + 'set-cookie': 'ham=eggs' + }) + res.end() + }) + + s.on('/'+landing, function (req, res) { + if (req.method !== 'GET') { // We should only accept GET redirects + console.error("Got a non-GET request to the redirect destination URL"); + res.writeHead(400); + res.end(); + return; + } + // Make sure the cookie doesn't get included twice, see #139: + // Make sure cookies are set properly after redirect + assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs'); + hits[landing] = true; + res.writeHead(200) + res.end(landing) + }) + } + + // Permanent bounce + var jar = new Jar() + jar.add(new Cookie('quux=baz')) + request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.perm, 'Original request is to /perm') + assert.ok(hits.perm_landing, 'Forward to permanent landing URL') + assert.equal(body, 'perm_landing', 'Got permanent landing content') + passed += 1 + done() + }) + + // Temporary bounce + request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + // Prevent bouncing. + request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode) + assert.ok(hits.nope, 'Original request to /nope') + assert.ok(!hits.nope_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 302, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow post redirects by default + request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when post') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow post redirects when followAllRedirects true + request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects by default + request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode < 301) throw new Error('Status is not a redirect.') + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects even if followRedirect is set to true + request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow delete redirects when followAllRedirects true + request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + var reqs_done = 0; + function done() { + reqs_done += 1; + if(reqs_done == 9) { + console.log(passed + ' tests passed.') + s.close() + } + } +}) diff --git a/node_modules/jsdom/node_modules/request/tests/test-s3.js b/node_modules/jsdom/node_modules/request/tests/test-s3.js new file mode 100644 index 0000000..5f59c4a --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-s3.js @@ -0,0 +1,13 @@ +var request = require('../main') + +var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', + { aws: + { key: 'AKIAI6KIQRRVMGK3WK5Q' + , secret: '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' + , bucket: 'log.curlybracecast.com' + } + }, function (e, resp, body) { + console.log(r.headers) + console.log(body) + } +) \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/request/tests/test-timeout.js b/node_modules/jsdom/node_modules/request/tests/test-timeout.js new file mode 100644 index 0000000..673f8ad --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/jsdom/node_modules/request/tests/test-toJSON.js b/node_modules/jsdom/node_modules/request/tests/test-toJSON.js new file mode 100644 index 0000000..b7c67ef --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-toJSON.js @@ -0,0 +1,14 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('asdf') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp) { + assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200) + s.close() + }) +}) \ No newline at end of file diff --git a/node_modules/jsdom/node_modules/request/tests/test-tunnel.js b/node_modules/jsdom/node_modules/request/tests/test-tunnel.js new file mode 100644 index 0000000..51e2126 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tests/test-tunnel.js @@ -0,0 +1,63 @@ +// test that we can tunnel a https request over an http proxy +// keeping all the CA and whatnot intact. +// +// Note: this requires that squid is installed. +// If the proxy fails to start, we'll just log a warning and assume success. + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt') + , ca = fs.readFileSync(caFile) + , child_process = require('child_process') + , sqConf = path.resolve(__dirname, 'squid.conf') + , sqArgs = ['-f', sqConf, '-N', '-d', '5'] + , proxy = 'http://localhost:3128' + , hadError = null + +var squid = child_process.spawn('squid', sqArgs); +var ready = false + +squid.stderr.on('data', function (c) { + console.error('SQUIDERR ' + c.toString().trim().split('\n') + .join('\nSQUIDERR ')) + ready = c.toString().match(/ready to serve requests/i) +}) + +squid.stdout.on('data', function (c) { + console.error('SQUIDOUT ' + c.toString().trim().split('\n') + .join('\nSQUIDOUT ')) +}) + +squid.on('exit', function (c) { + console.error('squid: exit '+c) + if (c && !ready) { + console.error('squid must be installed to run this test.') + console.error('skipping this test. please install squid and run again if you need to test tunneling.') + c = null + hadError = null + process.exit(0) + return + } + + if (c) { + hadError = hadError || new Error('Squid exited with '+c) + } + if (hadError) throw hadError +}) + +setTimeout(function F () { + if (!ready) return setTimeout(F, 100) + request({ uri: 'https://registry.npmjs.org/' + , proxy: 'http://localhost:3128' + , strictSSL: true + , ca: ca + , json: true }, function (er, body) { + hadError = er + console.log(er || typeof body) + if (!er) console.log("ok") + squid.kill('SIGKILL') + }) +}, 100) diff --git a/node_modules/jsdom/node_modules/request/tests/unicycle.jpg b/node_modules/jsdom/node_modules/request/tests/unicycle.jpg new file mode 100644 index 0000000..7cea4dd Binary files /dev/null and b/node_modules/jsdom/node_modules/request/tests/unicycle.jpg differ diff --git a/node_modules/jsdom/node_modules/request/tunnel.js b/node_modules/jsdom/node_modules/request/tunnel.js new file mode 100644 index 0000000..3f7bbb9 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/tunnel.js @@ -0,0 +1,227 @@ +'use strict' + +var net = require('net') + , tls = require('tls') + , http = require('http') + , https = require('https') + , events = require('events') + , assert = require('assert') + , util = require('util') + ; + +exports.httpOverHttp = httpOverHttp +exports.httpsOverHttp = httpsOverHttp +exports.httpOverHttps = httpOverHttps +exports.httpsOverHttps = httpsOverHttps + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + return agent +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + agent.createSocket = createSecureSocket + return agent +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + return agent +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + agent.createSocket = createSecureSocket + return agent +} + + +function TunnelingAgent(options) { + var self = this + self.options = options || {} + self.proxyOptions = self.options.proxy || {} + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets + self.requests = [] + self.sockets = [] + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i] + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1) + pending.request.onSocket(socket) + return + } + } + socket.destroy() + self.removeSocket(socket) + }) +} +util.inherits(TunnelingAgent, events.EventEmitter) + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}) + return + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree) + socket.on('close', onCloseOrRemove) + socket.on('agentRemove', onCloseOrRemove) + req.onSocket(socket) + + function onFree() { + self.emit('free', socket, host, port) + } + + function onCloseOrRemove(err) { + self.removeSocket() + socket.removeListener('free', onFree) + socket.removeListener('close', onCloseOrRemove) + socket.removeListener('agentRemove', onCloseOrRemove) + } + }) +} + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this + var placeholder = {} + self.sockets.push(placeholder) + + var connectOptions = mergeOptions({}, self.proxyOptions, + { method: 'CONNECT' + , path: options.host + ':' + options.port + , agent: false + } + ) + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {} + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64') + } + + debug('making CONNECT request') + var connectReq = self.request(connectOptions) + connectReq.useChunkedEncodingByDefault = false // for v0.6 + connectReq.once('response', onResponse) // for v0.6 + connectReq.once('upgrade', onUpgrade) // for v0.6 + connectReq.once('connect', onConnect) // for v0.7 or later + connectReq.once('error', onError) + connectReq.end() + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head) + }) + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners() + socket.removeAllListeners() + + if (res.statusCode === 200) { + assert.equal(head.length, 0) + debug('tunneling connection has established') + self.sockets[self.sockets.indexOf(placeholder)] = socket + cb(socket) + } else { + debug('tunneling socket could not be established, statusCode=%d', res.statusCode) + var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } + } + + function onError(cause) { + connectReq.removeAllListeners() + + debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack) + var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } +} + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) return + + this.sockets.splice(pos, 1) + + var pending = this.requests.shift() + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket) + }) + } +} + +function createSecureSocket(options, cb) { + var self = this + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, + { servername: options.host + , socket: socket + } + )) + cb(secureSocket) + }) +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i] + if (typeof overrides === 'object') { + var keys = Object.keys(overrides) + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j] + if (overrides[k] !== undefined) { + target[k] = overrides[k] + } + } + } + } + return target +} + + +var debug +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments) + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0] + } else { + args.unshift('TUNNEL:') + } + console.error.apply(console, args) + } +} else { + debug = function() {} +} +exports.debug = debug // for test diff --git a/node_modules/jsdom/node_modules/request/uuid.js b/node_modules/jsdom/node_modules/request/uuid.js new file mode 100644 index 0000000..fc0588b --- /dev/null +++ b/node_modules/jsdom/node_modules/request/uuid.js @@ -0,0 +1,19 @@ +module.exports = function () { + var s = [], itoh = '0123456789ABCDEF' + + // Make array of random hex digits. The UUID only has 32 digits in it, but we + // allocate an extra items to make room for the '-'s we'll be inserting. + for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10) + + // Conform to RFC-4122, section 4.4 + s[14] = 4; // Set 4 high bits of time_high field to version + s[19] = (s[19] & 0x3) | 0x8 // Specify 2 high bits of clock sequence + + // Convert to hex chars + for (var i = 0; i <36; i++) s[i] = itoh[s[i]] + + // Insert '-'s + s[8] = s[13] = s[18] = s[23] = '-' + + return s.join('') +} diff --git a/node_modules/jsdom/node_modules/request/vendor/cookie/index.js b/node_modules/jsdom/node_modules/request/vendor/cookie/index.js new file mode 100644 index 0000000..ff44b3e --- /dev/null +++ b/node_modules/jsdom/node_modules/request/vendor/cookie/index.js @@ -0,0 +1,65 @@ +/*! + * Tobi - Cookie + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var url = require('url'); + +/** + * Initialize a new `Cookie` with the given cookie `str` and `req`. + * + * @param {String} str + * @param {IncomingRequest} req + * @api private + */ + +var Cookie = exports = module.exports = function Cookie(str, req) { + this.str = str; + + // Map the key/val pairs + str.split(/ *; */).reduce(function(obj, pair){ + var p = pair.indexOf('='); + var key = p > 0 ? pair.substring(0, p).trim() : pair.trim(); + var lowerCasedKey = key.toLowerCase(); + var value = p > 0 ? pair.substring(p + 1).trim() : true; + + if (!obj.name) { + // First key is the name + obj.name = key; + obj.value = value; + } + else if (lowerCasedKey === 'httponly') { + obj.httpOnly = value; + } + else { + obj[lowerCasedKey] = value; + } + return obj; + }, this); + + // Expires + this.expires = this.expires + ? new Date(this.expires) + : Infinity; + + // Default or trim path + this.path = this.path + ? this.path.trim(): req + ? url.parse(req.url).pathname: '/'; +}; + +/** + * Return the original cookie string. + * + * @return {String} + * @api public + */ + +Cookie.prototype.toString = function(){ + return this.str; +}; diff --git a/node_modules/jsdom/node_modules/request/vendor/cookie/jar.js b/node_modules/jsdom/node_modules/request/vendor/cookie/jar.js new file mode 100644 index 0000000..34920e0 --- /dev/null +++ b/node_modules/jsdom/node_modules/request/vendor/cookie/jar.js @@ -0,0 +1,72 @@ +/*! +* Tobi - CookieJar +* Copyright(c) 2010 LearnBoost +* MIT Licensed +*/ + +/** +* Module dependencies. +*/ + +var url = require('url'); + +/** +* Initialize a new `CookieJar`. +* +* @api private +*/ + +var CookieJar = exports = module.exports = function CookieJar() { + this.cookies = []; +}; + +/** +* Add the given `cookie` to the jar. +* +* @param {Cookie} cookie +* @api private +*/ + +CookieJar.prototype.add = function(cookie){ + this.cookies = this.cookies.filter(function(c){ + // Avoid duplication (same path, same name) + return !(c.name == cookie.name && c.path == cookie.path); + }); + this.cookies.push(cookie); +}; + +/** +* Get cookies for the given `req`. +* +* @param {IncomingRequest} req +* @return {Array} +* @api private +*/ + +CookieJar.prototype.get = function(req){ + var path = url.parse(req.url).pathname + , now = new Date + , specificity = {}; + return this.cookies.filter(function(cookie){ + if (0 == path.indexOf(cookie.path) && now < cookie.expires + && cookie.path.length > (specificity[cookie.name] || 0)) + return specificity[cookie.name] = cookie.path.length; + }); +}; + +/** +* Return Cookie string for the given `req`. +* +* @param {IncomingRequest} req +* @return {String} +* @api private +*/ + +CookieJar.prototype.cookieString = function(req){ + var cookies = this.get(req); + if (cookies.length) { + return cookies.map(function(cookie){ + return cookie.name + '=' + cookie.value; + }).join('; '); + } +}; diff --git a/node_modules/jsdom/package.json b/node_modules/jsdom/package.json new file mode 100644 index 0000000..d781418 --- /dev/null +++ b/node_modules/jsdom/package.json @@ -0,0 +1,215 @@ +{ + "name": "jsdom", + "version": "0.3.4", + "description": "A JavaScript implementation of the W3C DOM", + "keywords": [ + "dom", + "w3c", + "html" + ], + "maintainers": [ + { + "name": "Elijah Insua", + "email": "tmpvar@gmail.com", + "url": "http://tmpvar.com" + }, + { + "name": "Domenic Denicola", + "email": "domenic@domenicdenicola.com", + "url": "http://domenicdenicola.com" + } + ], + "contributors": [ + { + "name": "Vincent Greene", + "email": "ulteriorlife@gmail.com" + }, + { + "name": "Dav Glass", + "email": "davglass@gmail.com" + }, + { + "name": "Felix Gnass", + "email": "fgnass@gmail.com" + }, + { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + }, + { + "name": "Aria Stewart", + "email": "aredridel@nbtsc.org" + }, + { + "name": "Matthew", + "email": "N.A.", + "url": "http://github.com/matthewpflueger/" + }, + { + "name": "Olivier El Mekki", + "email": "unknown", + "url": "http://blog.olivier-elmekki.com/" + }, + { + "name": "Shimon Dookdin", + "email": "helpmepro1@gmail.com" + }, + { + "name": "Daniel Cassidy", + "email": "mail@danielcassidy.me.uk", + "url": "http://www.danielcassidy.me.uk/" + }, + { + "name": "Sam Ruby", + "url": "http://intertwingly.net/blog/" + }, + { + "name": "hij1nx", + "url": "http://github.com/hij1nx" + }, + { + "name": "Yonathan Randolph", + "url": "http://github.com/yonran" + }, + { + "name": "Martin Davis", + "url": "http://github.com/waslogic" + }, + { + "name": "Andreas Lind Petersen", + "email": "andreas@one.com" + }, + { + "name": "d-ash", + "url": "http://github.com/d-ash" + }, + { + "name": "Robin Zhong", + "email": "fbzhong@gmail.com" + }, + { + "name": "Alexander Flatter", + "email": "flatter@gmail.com" + }, + { + "name": "Heng Liu", + "email": "liucougar@gmail.com" + }, + { + "name": "Brian McDaniel", + "url": "http://github.com/brianmcd" + }, + { + "name": "John Hurliman", + "email": "jhurliman@jhurliman.org" + }, + { + "name": "Jimmy Mabey" + }, + { + "name": "Gregory Tomlinson" + }, + { + "name": "Jason Davies", + "url": "http://www.jasondavies.com/" + }, + { + "name": "Josh Marshall", + "url": "http://www.ponderingtheobvious.com/" + }, + { + "name": "Jason Priestley", + "url": "https://github.com/jhp" + }, + { + "name": "Derek Lindahl", + "url": "https://github.com/dlindahl" + }, + { + "name": "Chris Roebuck", + "email": "chris@quillu.com", + "url": "http://www.quillu.com" + }, + { + "name": "Avi Deitcher", + "url": "https://github.com/deitch" + }, + { + "name": "Nao Iizuka", + "email": "iizuka@kyu-mu.net", + "url": "https://github.com/iizukanao" + }, + { + "name": "Peter Perenyi", + "url": "https://github.com/sinegar" + }, + { + "name": "Tiago Rodrigues", + "email": "tmcrodrigues@gmail.com", + "url": "http://trodrigues.net" + }, + { + "name": "Samori Gorse", + "email": "samorigorse@gmail.com", + "url": "http://github.com/shinuza" + }, + { + "name": "John Roberts", + "email": "jroberts@logitech.com" + }, + { + "name": "Chad Walker", + "email": "chad@chad-cat-lore-eddie.com", + "url": "https://github.com/chad3814" + } + ], + "bugs": { + "email": "tmpvar@gmail.com", + "url": "http://github.com/tmpvar/jsdom/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/tmpvar/jsdom/blob/master/LICENSE.txt" + } + ], + "repositories": [ + { + "type": "git", + "url": "http://github.com/tmpvar/jsdom.git" + } + ], + "implements": [ + "http://www.w3.org/TR/REC-DOM-Level-1" + ], + "dependencies": { + "htmlparser": "1.x", + "nwmatcher": ">=1.3.0", + "request": "2.x", + "cssom": "0.2.x", + "cssstyle": ">=0.2.3", + "contextify": "0.1.x" + }, + "optionalDependencies": { + "contextify": "0.1.x" + }, + "devDependencies": { + "nodeunit": ">=0.5.x", + "console.log": "*", + "html5": ">=0.3.8", + "optimist": "*" + }, + "directories": { + "lib": "./lib/jsdom" + }, + "scripts": { + "test": "node ./test/runner" + }, + "main": "./lib/jsdom", + "readme": "# jsdom\n\nA JavaScript implementation of the W3C DOM.\n\n## Install\n\n```bash\n$ npm install jsdom\n```\n\n## Human contact\n\nsee: [mailing list](http://groups.google.com/group/jsdom)\n\n## Easymode\n\nBootstrapping a DOM is generally a difficult process involving many error prone steps. We didn't want jsdom to fall into the same trap and that is why a new method, `jsdom.env()`, has been added in jsdom 0.2.0 which should make everyone's lives easier.\n\nwith URL\n\n```js\n// Count all of the links from the nodejs build page\nvar jsdom = require(\"jsdom\");\n\njsdom.env(\n \"http://nodejs.org/dist/\",\n [\"http://code.jquery.com/jquery.js\"],\n function (errors, window) {\n console.log(\"there have been\", window.$(\"a\").length, \"nodejs releases!\");\n }\n);\n```\n\nor with raw HTML\n\n```js\n// Run some jQuery on a html fragment\nvar jsdom = require(\"jsdom\");\n\njsdom.env(\n '

    jsdom\\'s Homepage

    ',\n [\"http://code.jquery.com/jquery.js\"],\n function(errors, window) {\n console.log(\"contents of a.the-link:\", window.$(\"a.the-link\").text());\n }\n);\n```\n\nor with a configuration object\n\n```js\n// Print all of the news items on hackernews\nvar jsdom = require(\"jsdom\");\n\njsdom.env({\n html: \"http://news.ycombinator.com/\",\n scripts: [\"http://code.jquery.com/jquery.js\"],\n done: function (errors, window) {\n var $ = window.$;\n console.log(\"HN Links\");\n $(\"td.title:not(:last) a\").each(function() {\n console.log(\" -\", $(this).text());\n });\n }\n});\n```\n\nor with raw JavaScript source\n\n```js\n// Print all of the news items on hackernews\nvar jsdom = require(\"jsdom\");\nvar fs = require(\"fs\");\nvar jquery = fs.readFileSync(\"./jquery.js\").toString();\n\njsdom.env({\n html: \"http://news.ycombinator.com/\",\n src: [jquery],\n done: function (errors, window) {\n var $ = window.$;\n console.log(\"HN Links\");\n $(\"td.title:not(:last) a\").each(function() {\n console.log(\" -\", $(this).text());\n });\n }\n});\n```\n\n### How it works\n`jsdom.env` is built for ease of use, which is rare in the world of the DOM! Since the web has some absolutely horrible JavaScript on it, as of jsdom 0.2.0 `jsdom.env` will not process external resources (scripts, images, etc). If you want to process the JavaScript use one of the methods below (`jsdom.jsdom` or `jsdom.jQueryify`)\n\n```js\njsdom.env(html, [scripts], [config], callback);\n```\n\n- `html` (**required**): may be a URL, HTML fragment, or file.\n- `scripts` (**optional**): may contain files or URLs.\n- `config` (**optional**): see below.\n- `callback` (**required**): takes two arguments:\n - `errors`: an array of errors\n - `window`: a brand new window\n\n_example:_\n\n```js\njsdom.env(html, function (errors, window) {\n // free memory associated with the window\n window.close();\n});\n```\n\nIf you would like to specify a configuration object only:\n\n```js\njsdom.env(config);\n```\n\n- `config.html`: see `html` above.\n- `config.scripts`: see `scripts` above.\n- `config.src`: an array of JavaScript strings that will be evaluated against the resulting document. Similar to `scripts`, but it accepts JavaScript instead of paths/URLs.\n- `config.done`: see `callback` above.\n- `config.document`:\n - `referer`: the new document will have this referer\n - `cookie`: manually set a cookie value, e.g. `'key=value; expires=Wed, Sep 21 2011 12:00:00 GMT; path=/'`\n- `config.features` : see `Flexibility` section below. **Note**: the default feature set for jsdom.env does _not_ include fetching remote JavaScript and executing it. This is something that you will need to **carefully** enable yourself.\n\n## For the hardcore\n\nIf you want to spawn a document/window and specify all sorts of options this is the section for you. This section covers the `jsdom.jsdom` method:\n\n```js\nvar jsdom = require(\"jsdom\").jsdom;\nvar doc = jsdom(markup, level, options);\nvar window = doc.createWindow();\n```\n\n- `markup` is an HTML/XML document to be parsed. You can also pass `null` or an undefined value to get a basic document with empty `` and `` tags. Document fragments are also supported (including `\"\"`), and will behave as sanely as possible (e.g. the resulting document will lack the `head`, `body` and `documentElement` properties if the corresponding elements aren't included).\n\n- `level` is `null` (which means level3) by default, but you can pass another level if you'd like.\n\n ```js\n var jsdom = require(\"jsdom\");\n var doc = jsdom.jsdom(\"\", jsdom.level(1, \"core\"));\n ```\n\n- `options` see the **Flexibility** section below.\n\n### Flexibility\n\nOne of the goals of jsdom is to be as minimal and light as possible. This section details how someone can change the behavior of `Document`s on the fly. These features are baked into the `DOMImplementation` that every `Document` has, and may be tweaked in two ways:\n\n1. When you create a new `Document` using the jsdom builder (`require(\"jsdom\").jsdom()`)\n\n ```js\n var jsdom = require(\"jsdom\").jsdom;\n var doc = jsdom(\"\", null, {\n features: {\n FetchExternalResources : [\"img\"]\n }\n });\n ```\n\n Do note, that this will only affect the document that is currently being created. All other documents will use the defaults specified below (see: Default Features).\n\n2. Before creating any documents, you can modify the defaults for all future documents:\n\n ```js\n require(\"jsdom\").defaultDocumentFeatures = {\n FetchExternalResources: [\"script\"],\n ProcessExternalResources: false\n };\n ```\n\n#### Default Features\n\nDefault features are extremely important for jsdom as they lower the configuration requirement and present developers a set of consistent default behaviors. The following sections detail the available features, their defaults, and the values that jsdom uses.\n\n\n`FetchExternalResources`\n\n- _Default_: `[\"script\"]`\n- _Allowed_: `[\"script\", \"img\", \"css\", \"frame\", \"iframe\", \"link\"]` or `false`\n\nEnables/disables fetching files over the file system/HTTP.\n\n`ProcessExternalResources`\n\n- _Default_: `[\"script\"]`\n- _Allowed_: `[\"script\"]` or `false`\n\nDisabling this will disable script execution (currently only JavaScript).\n\n`SkipExternalResources`\n\n- _Default_: `false`\n- _Allowed_: `/url to be skipped/` or `false`\n- _Example_: `/http:\\/\\/example.org/js/bad\\.js/`\n\nDo not download and process resources with url matching a regular expression.\n\n## Canvas\n\njsdom includes support for using the [canvas](https://npmjs.org/package/canvas) package to extend any `` elements with the canvas API. To make this work, you need to include canvas as a dependency in your project, as a peer of jsdom. If jsdom can find the canvas package, it will use it, but if it's not present, then `` elements will behave like `
    `s.\n\n# More Examples\n\n## Creating a document-less window\n\n```js\nvar jsdom = require(\"jsdom\");\nvar window = jsdom.createWindow();\n\nconsole.log(window.document); // output: undefined\n```\n\n## Creating a document\n\n```js\nvar jsdom = require(\"jsdom\");\nvar doc = new (jsdom.level(1, \"core\").Document)();\n\nconsole.log(doc.nodeName); // outputs: #document\n```\n\n## Creating a browser-like BOM/DOM/Window\n\n```js\nvar jsdom = require(\"jsdom\").jsdom;\nvar document = jsdom(\"hello world\");\nvar window = document.createWindow();\n\nconsole.log(window.document.innerHTML);\n// output: \"hello world\"\n\nconsole.log(window.innerWidth);\n// output: 1024\n\nconsole.log(typeof window.document.getElementsByClassName);\n// outputs: function\n```\n\n## jQueryify\n\n```js\nvar jsdom = require(\"jsdom\");\nvar window = jsdom.jsdom().createWindow();\n\njsdom.jQueryify(window, \"http://code.jquery.com/jquery.js\", function () {\n window.$(\"body\").append('
    Hello World, It works
    ');\n\n console.log(window.$(\".testing\").text());\n});\n```\n\n## Passing objects to scripts inside the page\n\n```js\nvar jsdom = require(\"jsdom\").jsdom;\nvar window = jsdom().createWindow();\n\nwindow.__myObject = { foo: \"bar\" };\n\nvar scriptEl = window.document.createElement(\"script\");\nscriptEl.src = \"anotherScript.js\";\nwindow.document.body.appendChild(scriptEl);\n\n// anotherScript.js will have the ability to read `window.__myObject`, even\n// though it originated in Node!\n```\n\n# Test Compliance:\n\n```\n level1/core 532/532 100%\n level1/html 238/238 100%\n level1/svg 527/527 100%\n level2/core 283/283 100%\n level2/html 697/697 100%\n level2/style 10/10 100%\n level2/extra 4/4 100%\n level2/events 24/24 100%\n level3/xpath 93/93 100%\n window/index 5/5 100%\n window/script 10/10 100%\n window/frame 14/14 100%\n sizzle/index 9/14 64%\n jsdom/index 86/86 100%\n jsonp/jsonp 1/1 100%\n browser/contextifyReplacement 4/4 100%\n browser/index 22/22 100%\n------------------------------------------------------\nTOTALS: 5/2564 failed; 99% success\n```\n\n## Running the tests\n\nFirst you'll want to `npm install`. To run all the tests, use `npm test`, which just calls `node test/runner`.\n\nUsing `test/runner` directly, you can slice and dice which tests your want to run from different levels. Usage is as follows:\n\n```\ntest/runner --help\nRun the jsdom test suite\n\nOptions:\n-s, --suites suites that you want to run. ie: -s level1/core,1/html,html [string]\n-f, --fail-fast stop on the first failed test\n-h, --help show the help\n-t, --tests choose the test cases to run. ie: -t jquery\n```\n", + "_id": "jsdom@0.3.4", + "dist": { + "shasum": "346d31d2efbfaa29843aeeabe28fb868a51da566" + }, + "_from": "jsdom" +} diff --git a/node_modules/jsdom/test.css b/node_modules/jsdom/test.css new file mode 100644 index 0000000..1e903c7 --- /dev/null +++ b/node_modules/jsdom/test.css @@ -0,0 +1,6 @@ + +@media screen,handheld { + .citation *.printonly { + display: none; + } +} diff --git a/node_modules/jsdom/test.js b/node_modules/jsdom/test.js new file mode 100644 index 0000000..83ba3ca --- /dev/null +++ b/node_modules/jsdom/test.js @@ -0,0 +1,17 @@ +"use strict"; + +var assert = require("assert"); +var jsdom = require("./lib/jsdom"); +var cssom = require("cssom"); + +console.log(cssom.parse(require("fs").readFileSync('test.css', 'utf-8'))); + +jsdom.env({ + html: '', + config: { + ProcessExternalResources: ["script", "link"] + }, + done: function (errors, window) { + window.getComputedStyle(window.document.body); + } +}); diff --git a/node_modules/request/LICENSE b/node_modules/request/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/request/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/request/README.md b/node_modules/request/README.md new file mode 100644 index 0000000..d1f5c56 --- /dev/null +++ b/node_modules/request/README.md @@ -0,0 +1,310 @@ +# Request -- Simplified HTTP request method + +## Install + +
    +  npm install request
    +
    + +Or from source: + +
    +  git clone git://github.com/mikeal/request.git 
    +  cd request
    +  npm link
    +
    + +## Super simple to use + +Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default. + +```javascript +var request = require('request'); +request('http://www.google.com', function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body) // Print the google web page. + } +}) +``` + +## Streaming + +You can stream any response to a file stream. + +```javascript +request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) +``` + +You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers. + +```javascript +fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json')) +``` + +Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers. + +```javascript +request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png')) +``` + +Now let's get fancy. + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + if (req.method === 'PUT') { + req.pipe(request.put('http://mysite.com/doodle.png')) + } else if (req.method === 'GET' || req.method === 'HEAD') { + request.get('http://mysite.com/doodle.png').pipe(resp) + } + } +}) +``` + +You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do: + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + var x = request('http://mysite.com/doodle.png') + req.pipe(x) + x.pipe(resp) + } +}) +``` + +And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :) + +```javascript +req.pipe(request('http://mysite.com/doodle.png')).pipe(resp) +``` + +Also, none of this new functionality conflicts with requests previous features, it just expands them. + +```javascript +var r = request.defaults({'proxy':'http://localproxy.com'}) + +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + r.get('http://google.com/doodle.png').pipe(resp) + } +}) +``` +You can still use intermediate proxies, the requests will still follow HTTP forwards, etc. + +## Forms + +`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API. + +Url encoded forms are simple + +```javascript +request.post('http://service.com/upload', {form:{key:'value'}}) +// or +request.post('http://service.com/upload').form({key:'value'}) +``` + +For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you. + +```javascript +var r = request.post('http://service.com/upload') +var form = r.form() +form.append('my_field', 'my_value') +form.append('my_buffer', new Buffer([1, 2, 3])) +form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png')) +form.append('remote_file', request('http://google.com/doodle.png')) +``` + +## OAuth Signing + +```javascript +// Twitter OAuth +var qs = require('querystring') + , oauth = + { callback: 'http://mysite.com/callback/' + , consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + } + , url = 'https://api.twitter.com/oauth/request_token' + ; +request.post({url:url, oauth:oauth}, function (e, r, body) { + // Assume by some stretch of magic you aquired the verifier + var access_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: access_token.oauth_token + , verifier: VERIFIER + , token_secret: access_token.oauth_token_secret + } + , url = 'https://api.twitter.com/oauth/access_token' + ; + request.post({url:url, oauth:oauth}, function (e, r, body) { + var perm_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: perm_token.oauth_token + , token_secret: perm_token.oauth_token_secret + } + , url = 'https://api.twitter.com/1/users/show.json?' + , params = + { screen_name: perm_token.screen_name + , user_id: perm_token.user_id + } + ; + url += qs.stringify(params) + request.get({url:url, oauth:oauth, json:true}, function (e, r, user) { + console.log(user) + }) + }) +}) +``` + + + +### request(options, callback) + +The first argument can be either a url or an options object. The only required option is uri, all others are optional. + +* `uri` || `url` - fully qualified uri or a parsed url object from url.parse() +* `qs` - object containing querystring values to be appended to the uri +* `method` - http method, defaults to GET +* `headers` - http headers, defaults to {} +* `body` - entity body for POST and PUT requests. Must be buffer or string. +* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request. +* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json. +* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below. +* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true. +* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false. +* `maxRedirects` - the maximum number of redirects to follow, defaults to 10. +* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer. +* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets. +* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. +* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request +* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri. +* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. +* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option. +* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section) +* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services) + + +The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer. + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. + +### request.put + +Same as request() but defaults to `method: "PUT"`. + +```javascript +request.put(url) +``` + +### request.post + +Same as request() but defaults to `method: "POST"`. + +```javascript +request.post(url) +``` + +### request.head + +Same as request() but defaults to `method: "HEAD"`. + +```javascript +request.head(url) +``` + +### request.del + +Same as request() but defaults to `method: "DELETE"`. + +```javascript +request.del(url) +``` + +### request.get + +Alias to normal request method for uniformity. + +```javascript +request.get(url) +``` +### request.cookie + +Function that creates a new cookie. + +```javascript +request.cookie('cookie_string_here') +``` +### request.jar + +Function that creates a new cookie jar. + +```javascript +request.jar() +``` + + +## Examples: + +```javascript + var request = require('request') + , rand = Math.floor(Math.random()*100000000).toString() + ; + request( + { method: 'PUT' + , uri: 'http://mikeal.iriscouch.com/testjs/' + rand + , multipart: + [ { 'content-type': 'application/json' + , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) + } + , { body: 'I am an attachment' } + ] + } + , function (error, response, body) { + if(response.statusCode == 201){ + console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand) + } else { + console.log('error: '+ response.statusCode) + console.log(body) + } + } + ) +``` +Cookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent). + +```javascript +var request = request.defaults({jar: false}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` + +If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option: + +```javascript +var j = request.jar() +var request = request.defaults({jar:j}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` +OR + +```javascript +var j = request.jar() +var cookie = request.cookie('your_cookie_here') +j.add(cookie) +request({url: 'http://www.google.com', jar: j}, function () { + request('http://images.google.com') +}) +``` diff --git a/node_modules/request/aws.js b/node_modules/request/aws.js new file mode 100644 index 0000000..4d8d950 --- /dev/null +++ b/node_modules/request/aws.js @@ -0,0 +1,191 @@ + +/*! + * knox - auth + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var crypto = require('crypto') + , parse = require('url').parse + ; + +/** + * Valid keys. + */ + +var keys = + [ 'acl' + , 'location' + , 'logging' + , 'notification' + , 'partNumber' + , 'policy' + , 'requestPayment' + , 'torrent' + , 'uploadId' + , 'uploads' + , 'versionId' + , 'versioning' + , 'versions' + , 'website' + ] + +/** + * Return an "Authorization" header value with the given `options` + * in the form of "AWS :" + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.authorization = function(options){ + return 'AWS ' + options.key + ':' + exports.sign(options) +} + +/** + * Simple HMAC-SHA1 Wrapper + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.hmacSha1 = function(options){ + return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64') +} + +/** + * Create a base64 sha1 HMAC for `options`. + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.sign = function(options){ + options.message = exports.stringToSign(options) + return exports.hmacSha1(options) +} + +/** + * Create a base64 sha1 HMAC for `options`. + * + * Specifically to be used with S3 presigned URLs + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.signQuery = function(options){ + options.message = exports.queryStringToSign(options) + return exports.hmacSha1(options) +} + +/** + * Return a string for sign() with the given `options`. + * + * Spec: + * + * \n + * \n + * \n + * \n + * [headers\n] + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.stringToSign = function(options){ + var headers = options.amazonHeaders || '' + if (headers) headers += '\n' + var r = + [ options.verb + , options.md5 + , options.contentType + , options.date.toUTCString() + , headers + options.resource + ] + return r.join('\n') +} + +/** + * Return a string for sign() with the given `options`, but is meant exclusively + * for S3 presigned URLs + * + * Spec: + * + * \n + * + * + * @param {Object} options + * @return {String} + * @api private + */ + +exports.queryStringToSign = function(options){ + return 'GET\n\n\n' + options.date + '\n' + options.resource +}; + +/** + * Perform the following: + * + * - ignore non-amazon headers + * - lowercase fields + * - sort lexicographically + * - trim whitespace between ":" + * - join with newline + * + * @param {Object} headers + * @return {String} + * @api private + */ + +exports.canonicalizeHeaders = function(headers){ + var buf = [] + , fields = Object.keys(headers) + ; + for (var i = 0, len = fields.length; i < len; ++i) { + var field = fields[i] + , val = headers[field] + , field = field.toLowerCase() + ; + if (0 !== field.indexOf('x-amz')) continue + buf.push(field + ':' + val) + } + return buf.sort().join('\n') +}; + +/** + * Perform the following: + * + * - ignore non sub-resources + * - sort lexicographically + * + * @param {String} resource + * @return {String} + * @api private + */ + +exports.canonicalizeResource = function(resource){ + var url = parse(resource, true) + , path = url.pathname + , buf = [] + ; + + Object.keys(url.query).forEach(function(key){ + if (!~keys.indexOf(key)) return + var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]) + buf.push(key + val) + }) + + return path + (buf.length ? '?' + buf.sort().join('&') : '') +}; diff --git a/node_modules/request/forever.js b/node_modules/request/forever.js new file mode 100644 index 0000000..1e1d4b9 --- /dev/null +++ b/node_modules/request/forever.js @@ -0,0 +1,103 @@ +module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL + +var util = require('util') + , Agent = require('http').Agent + , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent + +function ForeverAgent(options) { + var self = this + self.options = options || {} + self.requests = {} + self.sockets = {} + self.freeSockets = {} + self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets + self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets + self.on('free', function(socket, host, port) { + var name = host + ':' + port + if (self.requests[name] && self.requests[name].length) { + self.requests[name].shift().onSocket(socket) + } else if (self.sockets[name].length < self.minSockets) { + if (!self.freeSockets[name]) self.freeSockets[name] = [] + self.freeSockets[name].push(socket) + + // if an error happens while we don't use the socket anyway, meh, throw the socket away + function onIdleError() { + socket.destroy() + } + socket._onIdleError = onIdleError + socket.on('error', onIdleError) + } else { + // If there are no pending requests just destroy the + // socket and it will get removed from the pool. This + // gets us out of timeout issues and allows us to + // default to Connection:keep-alive. + socket.destroy() + } + }) + +} +util.inherits(ForeverAgent, Agent) + +ForeverAgent.defaultMinSockets = 5 + + +ForeverAgent.prototype.createConnection = net.createConnection +ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest +ForeverAgent.prototype.addRequest = function(req, host, port) { + var name = host + ':' + port + if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { + var idleSocket = this.freeSockets[name].pop() + idleSocket.removeListener('error', idleSocket._onIdleError) + delete idleSocket._onIdleError + req._reusedSocket = true + req.onSocket(idleSocket) + } else { + this.addRequestNoreuse(req, host, port) + } +} + +ForeverAgent.prototype.removeSocket = function(s, name, host, port) { + if (this.sockets[name]) { + var index = this.sockets[name].indexOf(s) + if (index !== -1) { + this.sockets[name].splice(index, 1) + } + } else if (this.sockets[name] && this.sockets[name].length === 0) { + // don't leak + delete this.sockets[name] + delete this.requests[name] + } + + if (this.freeSockets[name]) { + var index = this.freeSockets[name].indexOf(s) + if (index !== -1) { + this.freeSockets[name].splice(index, 1) + if (this.freeSockets[name].length === 0) { + delete this.freeSockets[name] + } + } + } + + if (this.requests[name] && this.requests[name].length) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(name, host, port).emit('free') + } +} + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + options.port = port + options.host = host + return tls.connect(options) +} diff --git a/node_modules/request/main.js b/node_modules/request/main.js new file mode 100644 index 0000000..27b470b --- /dev/null +++ b/node_modules/request/main.js @@ -0,0 +1,1123 @@ +// Copyright 2010-2012 Mikeal Rogers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var http = require('http') + , https = false + , tls = false + , url = require('url') + , util = require('util') + , stream = require('stream') + , qs = require('querystring') + , oauth = require('./oauth') + , uuid = require('./uuid') + , ForeverAgent = require('./forever') + , Cookie = require('./vendor/cookie') + , CookieJar = require('./vendor/cookie/jar') + , cookieJar = new CookieJar + , tunnel = require('./tunnel') + , aws = require('./aws') + + , mime = require('mime') + , FormData = require('form-data') + ; + +if (process.logging) { + var log = process.logging('request') +} + +try { + https = require('https') +} catch (e) {} + +try { + tls = require('tls') +} catch (e) {} + +function toBase64 (str) { + return (new Buffer(str || "", "ascii")).toString("base64") +} + +// Hacky fix for pre-0.4.4 https +if (https && !https.Agent) { + https.Agent = function (options) { + http.Agent.call(this, options) + } + util.inherits(https.Agent, http.Agent) + https.Agent.prototype._getConnection = function (host, port, cb) { + var s = tls.connect(port, host, this.options, function () { + // do other checks here? + if (cb) cb() + }) + return s + } +} + +function isReadStream (rs) { + if (rs.readable && rs.path && rs.mode) { + return true + } +} + +function copy (obj) { + var o = {} + Object.keys(obj).forEach(function (i) { + o[i] = obj[i] + }) + return o +} + +var isUrl = /^https?:/ + +var globalPool = {} + +function Request (options) { + stream.Stream.call(this) + this.readable = true + this.writable = true + + if (typeof options === 'string') { + options = {uri:options} + } + + var reserved = Object.keys(Request.prototype) + for (var i in options) { + if (reserved.indexOf(i) === -1) { + this[i] = options[i] + } else { + if (typeof options[i] === 'function') { + delete options[i] + } + } + } + options = copy(options) + + this.init(options) +} +util.inherits(Request, stream.Stream) +Request.prototype.init = function (options) { + var self = this + + if (!options) options = {} + if (process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG)) console.error('REQUEST', options) + if (!self.pool && self.pool !== false) self.pool = globalPool + self.dests = [] + self.__isRequestRequest = true + + // Protect against double callback + if (!self._callback && self.callback) { + self._callback = self.callback + self.callback = function () { + if (self._callbackCalled) return // Print a warning maybe? + self._callback.apply(self, arguments) + self._callbackCalled = true + } + self.on('error', self.callback.bind()) + self.on('complete', self.callback.bind(self, null)) + } + + if (self.url) { + // People use this property instead all the time so why not just support it. + self.uri = self.url + delete self.url + } + + if (!self.uri) { + // this will throw if unhandled but is handleable when in a redirect + return self.emit('error', new Error("options.uri is a required argument")) + } else { + if (typeof self.uri == "string") self.uri = url.parse(self.uri) + } + if (self.proxy) { + if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port + , proxyAuth: self.proxy.auth } + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } + } + + if (!self.uri.host || !self.uri.pathname) { + // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar + // Detect and reject it as soon as possible + var faultyUri = url.format(self.uri) + var message = 'Invalid URI "' + faultyUri + '"' + if (Object.keys(options).length === 0) { + // No option ? This can be the sign of a redirect + // As this is a case where the user cannot do anything (he didn't call request directly with this URL) + // he should be warned that it can be caused by a redirection (can save some hair) + message += '. This can be caused by a crappy redirection.' + } + self.emit('error', new Error(message)) + return // This error was fatal + } + + self._redirectsFollowed = self._redirectsFollowed || 0 + self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 + self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true + self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false + if (self.followRedirect || self.followAllRedirects) + self.redirects = self.redirects || [] + + self.headers = self.headers ? copy(self.headers) : {} + + self.setHost = false + if (!self.headers.host) { + self.headers.host = self.uri.hostname + if (self.uri.port) { + if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && + !(self.uri.port === 443 && self.uri.protocol === 'https:') ) + self.headers.host += (':'+self.uri.port) + } + self.setHost = true + } + + self.jar(self._jar || options.jar) + + if (!self.uri.pathname) {self.uri.pathname = '/'} + if (!self.uri.port) { + if (self.uri.protocol == 'http:') {self.uri.port = 80} + else if (self.uri.protocol == 'https:') {self.uri.port = 443} + } + + if (self.proxy && !self.tunnel) { + self.port = self.proxy.port + self.host = self.proxy.hostname + } else { + self.port = self.uri.port + self.host = self.uri.hostname + } + + self.clientErrorHandler = function (error) { + if (self._aborted) return + + if (self.setHost) delete self.headers.host + if (self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } + self.start() + self.req.end() + return + } + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + self.emit('error', error) + } + + self._parserErrorHandler = function (error) { + if (this.res) { + if (this.res.request) { + this.res.request.emit('error', error) + } else { + this.res.emit('error', error) + } + } else { + this._httpMessage.emit('error', error) + } + } + + if (options.form) { + self.form(options.form) + } + + if (options.oauth) { + self.oauth(options.oauth) + } + + if (options.aws) { + self.aws(options.aws) + } + + if (self.uri.auth && !self.headers.authorization) { + self.headers.authorization = "Basic " + toBase64(self.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { + self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + + if (options.qs) self.qs(options.qs) + + if (self.uri.path) { + self.path = self.uri.path + } else { + self.path = self.uri.pathname + (self.uri.search || "") + } + + if (self.path.length === 0) self.path = '/' + + if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + + if (options.json) { + self.json(options.json) + } else if (options.multipart) { + self.boundary = uuid() + self.multipart(options.multipart) + } + + if (self.body) { + var length = 0 + if (!Buffer.isBuffer(self.body)) { + if (Array.isArray(self.body)) { + for (var i = 0; i < self.body.length; i++) { + length += self.body[i].length + } + } else { + self.body = new Buffer(self.body) + length = self.body.length + } + } else { + length = self.body.length + } + if (length) { + if(!self.headers['content-length'] && !self.headers['Content-Length']) + self.headers['content-length'] = length + } else { + throw new Error('Argument error, options.body.') + } + } + + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol + , defaultModules = {'http:':http, 'https:':https} + , httpModules = self.httpModules || {} + ; + self.httpModule = httpModules[protocol] || defaultModules[protocol] + + if (!self.httpModule) return this.emit('error', new Error("Invalid protocol")) + + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + if (options.agentClass) { + self.agentClass = options.agentClass + } else if (options.forever) { + self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL + } else { + self.agentClass = self.httpModule.Agent + } + } + + if (self.pool === false) { + self.agent = false + } else { + self.agent = self.agent || self.getAgent() + if (self.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.maxSockets + } + if (self.pool.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent.maxSockets = self.pool.maxSockets + } + } + + self.once('pipe', function (src) { + if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.") + self.src = src + if (isReadStream(src)) { + if (!self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = mime.lookup(src.path) + } else { + if (src.headers) { + for (var i in src.headers) { + if (!self.headers[i]) { + self.headers[i] = src.headers[i] + } + } + } + if (self._json && !self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = 'application/json' + if (src.method && !self.method) { + self.method = src.method + } + } + + self.on('pipe', function () { + console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") + }) + }) + + process.nextTick(function () { + if (self._aborted) return + + if (self._form) { + self.setHeaders(self._form.getHeaders()) + self._form.pipe(self) + } + if (self.body) { + if (Array.isArray(self.body)) { + self.body.forEach(function (part) { + self.write(part) + }) + } else { + self.write(self.body) + } + self.end() + } else if (self.requestBodyStream) { + console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") + self.requestBodyStream.pipe(self) + } else if (!self.src) { + if (self.method !== 'GET' && typeof self.method !== 'undefined') { + self.headers['content-length'] = 0 + } + self.end() + } + self.ntick = true + }) +} + +// Must call this when following a redirect from https to http or vice versa +// Attempts to keep everything as identical as possible, but update the +// httpModule, Tunneling agent, and/or Forever Agent in use. +Request.prototype._updateProtocol = function () { + var self = this + var protocol = self.uri.protocol + + if (protocol === 'https:') { + // previously was doing http, now doing https + // if it's https, then we might need to tunnel now. + if (self.proxy) { + self.tunnel = true + var tunnelFn = self.proxy.protocol === 'http:' + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + var tunnelOptions = { proxy: { host: self.proxy.hostname + , post: +self.proxy.port + , proxyAuth: self.proxy.auth } + , ca: self.ca } + self.agent = tunnelFn(tunnelOptions) + return + } + + self.httpModule = https + switch (self.agentClass) { + case ForeverAgent: + self.agentClass = ForeverAgent.SSL + break + case http.Agent: + self.agentClass = https.Agent + break + default: + // nothing we can do. Just hope for the best. + return + } + + // if there's an agent, we need to get a new one. + if (self.agent) self.agent = self.getAgent() + + } else { + if (log) log('previously https, now http') + // previously was doing https, now doing http + // stop any tunneling. + if (self.tunnel) self.tunnel = false + self.httpModule = http + switch (self.agentClass) { + case ForeverAgent.SSL: + self.agentClass = ForeverAgent + break + case https.Agent: + self.agentClass = http.Agent + break + default: + // nothing we can do. just hope for the best + return + } + + // if there's an agent, then get a new one. + if (self.agent) { + self.agent = null + self.agent = self.getAgent() + } + } +} + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.httpModule.Agent) { + poolKey += Agent.name + } + + if (!this.httpModule.globalAgent) { + // node 0.4.x + options.host = this.host + options.port = this.port + if (poolKey) poolKey += ':' + poolKey += this.host + ':' + this.port + } + + // ca option is only relevant if proxy or destination are https + var proxy = this.proxy + if (typeof proxy === 'string') proxy = url.parse(proxy) + var caRelevant = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:' + if (options.ca && caRelevant) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // we're using a stored agent. Make sure it's protocol-specific + poolKey = this.uri.protocol + poolKey + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) +} + +Request.prototype.start = function () { + var self = this + + if (self._aborted) return + + self._started = true + self.method = self.method || 'GET' + self.href = self.uri.href + if (log) log('%method %href', self) + + if (self.src && self.src.stat && self.src.stat.size && !self.headers['content-length'] && !self.headers['Content-Length']) { + self.headers['content-length'] = self.src.stat.size + } + if (self._aws) { + self.aws(self._aws, true) + } + self.req = self.httpModule.request(self, function (response) { + if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) { + response.connection.once('error', self._parserErrorHandler) + } + if (self._aborted) return + if (self._paused) response.pause() + + self.response = response + response.request = self + response.toJSON = toJSON + + if (self.httpModule === https && + self.strictSSL && + !response.client.authorized) { + var sslErr = response.client.authorizationError + self.emit('error', new Error('SSL Error: '+ sslErr)) + return + } + + if (self.setHost) delete self.headers.host + if (self.timeout && self.timeoutTimer) { + clearTimeout(self.timeoutTimer) + self.timeoutTimer = null + } + + var addCookie = function (cookie) { + if (self._jar) self._jar.add(new Cookie(cookie)) + else cookieJar.add(new Cookie(cookie)) + } + + if (response.headers['set-cookie'] && (!self._disableCookies)) { + if (Array.isArray(response.headers['set-cookie'])) response.headers['set-cookie'].forEach(addCookie) + else addCookie(response.headers['set-cookie']) + } + + if (response.statusCode >= 300 && response.statusCode < 400 && + (self.followAllRedirects || + (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST' && self.method !== 'DELETE'))) && + response.headers.location) { + if (self._redirectsFollowed >= self.maxRedirects) { + self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+self.uri.href)) + return + } + self._redirectsFollowed += 1 + + if (!isUrl.test(response.headers.location)) { + response.headers.location = url.resolve(self.uri.href, response.headers.location) + } + + var uriPrev = self.uri + self.uri = url.parse(response.headers.location) + + // handle the case where we change protocol from https to http or vice versa + if (self.uri.protocol !== uriPrev.protocol) { + self._updateProtocol() + } + + self.redirects.push( + { statusCode : response.statusCode + , redirectUri: response.headers.location + } + ) + if (self.followAllRedirects) self.method = 'GET' + // self.method = 'GET' // Force all redirects to use GET || commented out fixes #215 + delete self.src + delete self.req + delete self.agent + delete self._started + delete self.body + delete self._form + if (self.headers) { + delete self.headers.host + delete self.headers['content-type'] + delete self.headers['content-length'] + } + if (log) log('Redirect to %uri', self) + self.init() + return // Ignore the rest of the response + } else { + self._redirectsFollowed = self._redirectsFollowed || 0 + // Be a good stream and emit end when the response is finished. + // Hack to emit end on close because of a core bug that never fires end + response.on('close', function () { + if (!self._ended) self.response.emit('end') + }) + + if (self.encoding) { + if (self.dests.length !== 0) { + console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") + } else { + response.setEncoding(self.encoding) + } + } + + self.dests.forEach(function (dest) { + self.pipeDest(dest) + }) + + response.on("data", function (chunk) { + self._destdata = true + self.emit("data", chunk) + }) + response.on("end", function (chunk) { + self._ended = true + self.emit("end", chunk) + }) + response.on("close", function () {self.emit("close")}) + + self.emit('response', response) + + if (self.callback) { + var buffer = [] + var bodyLen = 0 + self.on("data", function (chunk) { + buffer.push(chunk) + bodyLen += chunk.length + }) + self.on("end", function () { + if (self._aborted) return + + if (buffer.length && Buffer.isBuffer(buffer[0])) { + var body = new Buffer(bodyLen) + var i = 0 + buffer.forEach(function (chunk) { + chunk.copy(body, i, 0, chunk.length) + i += chunk.length + }) + if (self.encoding === null) { + response.body = body + } else { + response.body = body.toString(self.encoding) + } + } else if (buffer.length) { + response.body = buffer.join('') + } + + if (self._json) { + try { + response.body = JSON.parse(response.body) + } catch (e) {} + } + + self.emit('complete', response, response.body) + }) + } + } + }) + + if (self.timeout && !self.timeoutTimer) { + self.timeoutTimer = setTimeout(function () { + self.req.abort() + var e = new Error("ETIMEDOUT") + e.code = "ETIMEDOUT" + self.emit("error", e) + }, self.timeout) + + // Set additional timeout on socket - in case if remote + // server freeze after sending headers + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function () { + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } + } + + self.req.on('error', self.clientErrorHandler) + self.req.on('drain', function() { + self.emit('drain') + }) + self.on('end', function() { + if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler) + }) + self.emit('request', self.req) +} + +Request.prototype.abort = function () { + this._aborted = true + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + +Request.prototype.pipeDest = function (dest) { + var response = this.response + // Called after the response is received + if (dest.headers) { + dest.headers['content-type'] = response.headers['content-type'] + if (response.headers['content-length']) { + dest.headers['content-length'] = response.headers['content-length'] + } + } + if (dest.setHeader) { + for (var i in response.headers) { + dest.setHeader(i, response.headers[i]) + } + dest.statusCode = response.statusCode + } + if (this.pipefilter) this.pipefilter(response, dest) +} + +// Composable API +Request.prototype.setHeader = function (name, value, clobber) { + if (clobber === undefined) clobber = true + if (clobber || !this.headers.hasOwnProperty(name)) this.headers[name] = value + else this.headers[name] += ',' + value + return this +} +Request.prototype.setHeaders = function (headers) { + for (var i in headers) {this.setHeader(i, headers[i])} + return this +} +Request.prototype.qs = function (q, clobber) { + var base + if (!clobber && this.uri.query) base = qs.parse(this.uri.query) + else base = {} + + for (var i in q) { + base[i] = q[i] + } + + this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base)) + this.url = this.uri + + return this +} +Request.prototype.form = function (form) { + if (form) { + this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' + this.body = qs.stringify(form).toString('utf8') + return this + } + // create form-data object + this._form = new FormData() + return this._form +} +Request.prototype.multipart = function (multipart) { + var self = this + self.body = [] + + if (!self.headers['content-type']) { + self.headers['content-type'] = 'multipart/related; boundary=' + self.boundary + } else { + self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary + } + + if (!multipart.forEach) throw new Error('Argument error, options.multipart.') + + if (self.preambleCRLF) { + self.body.push(new Buffer('\r\n')) + } + + multipart.forEach(function (part) { + var body = part.body + if(body == null) throw Error('Body attribute missing in multipart.') + delete part.body + var preamble = '--' + self.boundary + '\r\n' + Object.keys(part).forEach(function (key) { + preamble += key + ': ' + part[key] + '\r\n' + }) + preamble += '\r\n' + self.body.push(new Buffer(preamble)) + self.body.push(new Buffer(body)) + self.body.push(new Buffer('\r\n')) + }) + self.body.push(new Buffer('--' + self.boundary + '--')) + return self +} +Request.prototype.json = function (val) { + this.setHeader('accept', 'application/json') + this._json = true + if (typeof val === 'boolean') { + if (typeof this.body === 'object') { + this.setHeader('content-type', 'application/json') + this.body = JSON.stringify(this.body) + } + } else { + this.setHeader('content-type', 'application/json') + this.body = JSON.stringify(val) + } + return this +} +function getHeader(name, headers) { + var result, re, match + Object.keys(headers).forEach(function (key) { + re = new RegExp(name, 'i') + match = key.match(re) + if (match) result = headers[key] + }) + return result +} +Request.prototype.aws = function (opts, now) { + if (!now) { + this._aws = opts + return this + } + var date = new Date() + this.setHeader('date', date.toUTCString()) + var auth = + { key: opts.key + , secret: opts.secret + , verb: this.method.toUpperCase() + , date: date + , contentType: getHeader('content-type', this.headers) || '' + , md5: getHeader('content-md5', this.headers) || '' + , amazonHeaders: aws.canonicalizeHeaders(this.headers) + } + if (opts.bucket && this.path) { + auth.resource = '/' + opts.bucket + this.path + } else if (opts.bucket && !this.path) { + auth.resource = '/' + opts.bucket + } else if (!opts.bucket && this.path) { + auth.resource = this.path + } else if (!opts.bucket && !this.path) { + auth.resource = '/' + } + auth.resource = aws.canonicalizeResource(auth.resource) + this.setHeader('authorization', aws.authorization(auth)) + + return this +} + +Request.prototype.oauth = function (_oauth) { + var form + if (this.headers['content-type'] && + this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) === + 'application/x-www-form-urlencoded' + ) { + form = qs.parse(this.body) + } + if (this.uri.query) { + form = qs.parse(this.uri.query) + } + if (!form) form = {} + var oa = {} + for (var i in form) oa[i] = form[i] + for (var i in _oauth) oa['oauth_'+i] = _oauth[i] + if (!oa.oauth_version) oa.oauth_version = '1.0' + if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( (new Date()).getTime() / 1000 ).toString() + if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') + + oa.oauth_signature_method = 'HMAC-SHA1' + + var consumer_secret = oa.oauth_consumer_secret + delete oa.oauth_consumer_secret + var token_secret = oa.oauth_token_secret + delete oa.oauth_token_secret + + var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname + var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret) + + // oa.oauth_signature = signature + for (var i in form) { + if ( i.slice(0, 'oauth_') in _oauth) { + // skip + } else { + delete oa['oauth_'+i] + if (i !== 'x_auth_mode') delete oa[i] + } + } + this.headers.Authorization = + 'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',') + this.headers.Authorization += ',oauth_signature="' + oauth.rfc3986(signature) + '"' + return this +} +Request.prototype.jar = function (jar) { + var cookies + + if (this._redirectsFollowed === 0) { + this.originalCookieHeader = this.headers.cookie + } + + if (jar === false) { + // disable cookies + cookies = false + this._disableCookies = true + } else if (jar) { + // fetch cookie from the user defined cookie jar + cookies = jar.get({ url: this.uri.href }) + } else { + // fetch cookie from the global cookie jar + cookies = cookieJar.get({ url: this.uri.href }) + } + + if (cookies && cookies.length) { + var cookieString = cookies.map(function (c) { + return c.name + "=" + c.value + }).join("; ") + + if (this.originalCookieHeader) { + // Don't overwrite existing Cookie header + this.headers.cookie = this.originalCookieHeader + '; ' + cookieString + } else { + this.headers.cookie = cookieString + } + } + this._jar = jar + return this +} + + +// Stream API +Request.prototype.pipe = function (dest, opts) { + if (this.response) { + if (this._destdata) { + throw new Error("You cannot pipe after data has been emitted from the response.") + } else if (this._ended) { + throw new Error("You cannot pipe after the response has been ended.") + } else { + stream.Stream.prototype.pipe.call(this, dest, opts) + this.pipeDest(dest) + return dest + } + } else { + this.dests.push(dest) + stream.Stream.prototype.pipe.call(this, dest, opts) + return dest + } +} +Request.prototype.write = function () { + if (!this._started) this.start() + return this.req.write.apply(this.req, arguments) +} +Request.prototype.end = function (chunk) { + if (chunk) this.write(chunk) + if (!this._started) this.start() + this.req.end() +} +Request.prototype.pause = function () { + if (!this.response) this._paused = true + else this.response.pause.apply(this.response, arguments) +} +Request.prototype.resume = function () { + if (!this.response) this._paused = false + else this.response.resume.apply(this.response, arguments) +} +Request.prototype.destroy = function () { + if (!this._ended) this.end() +} + +// organize params for post, put, head, del +function initParams(uri, options, callback) { + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + uri = options.uri + } + return { uri: uri, options: options, callback: callback } +} + +function request (uri, options, callback) { + if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.') + if ((typeof options === 'function') && !callback) callback = options + if (options && typeof options === 'object') { + options.uri = uri + } else if (typeof uri === 'string') { + options = {uri:uri} + } else { + options = uri + } + + if (callback) options.callback = callback + var r = new Request(options) + return r +} + +module.exports = request + +request.initParams = initParams + +request.defaults = function (options, requester) { + var def = function (method) { + var d = function (uri, opts, callback) { + var params = initParams(uri, opts, callback) + for (var i in options) { + if (params.options[i] === undefined) params.options[i] = options[i] + } + if(typeof requester === 'function') { + if(method === request) { + method = requester + } else { + params.options._requester = requester + } + } + return method(params.options, params.callback) + } + return d + } + var de = def(request) + de.get = def(request.get) + de.post = def(request.post) + de.put = def(request.put) + de.head = def(request.head) + de.del = def(request.del) + de.cookie = def(request.cookie) + de.jar = request.jar + return de +} + +request.forever = function (agentOptions, optionsArg) { + var options = {} + if (optionsArg) { + for (option in optionsArg) { + options[option] = optionsArg[option] + } + } + if (agentOptions) options.agentOptions = agentOptions + options.forever = true + return request.defaults(options) +} + +request.get = request +request.post = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'POST' + return request(params.uri || null, params.options, params.callback) +} +request.put = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'PUT' + return request(params.uri || null, params.options, params.callback) +} +request.head = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'HEAD' + if (params.options.body || + params.options.requestBodyStream || + (params.options.json && typeof params.options.json !== 'boolean') || + params.options.multipart) { + throw new Error("HTTP HEAD requests MUST NOT include a request body.") + } + return request(params.uri || null, params.options, params.callback) +} +request.del = function (uri, options, callback) { + var params = initParams(uri, options, callback) + params.options.method = 'DELETE' + if(typeof params.options._requester === 'function') { + request = params.options._requester + } + return request(params.uri || null, params.options, params.callback) +} +request.jar = function () { + return new CookieJar +} +request.cookie = function (str) { + if (str && str.uri) str = str.uri + if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") + return new Cookie(str) +} + +// Safe toJSON + +function getSafe (self, uuid) { + if (typeof self === 'object' || typeof self === 'function') var safe = {} + if (Array.isArray(self)) var safe = [] + + var recurse = [] + + Object.defineProperty(self, uuid, {}) + + var attrs = Object.keys(self).filter(function (i) { + if (i === uuid) return false + if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true + return !(Object.getOwnPropertyDescriptor(self[i], uuid)) + }) + + + for (var i=0;i $(BUILDDIR)/async.min.js + +test: + nodeunit test + +clean: + rm -rf $(BUILDDIR) + +lint: + nodelint --config nodelint.cfg lib/async.js + +.PHONY: test build all diff --git a/node_modules/request/node_modules/form-data/node_modules/async/README.md b/node_modules/request/node_modules/form-data/node_modules/async/README.md new file mode 100644 index 0000000..039d942 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/README.md @@ -0,0 +1,970 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, forEach…) as well as some common patterns +for asynchronous flow control (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + + async.parallel([ + function(){ ... }, + function(){ ... } + ], callback); + + async.series([ + function(){ ... }, + function(){ ... } + ]); + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + + +## Download + +Releases are available for download from +[GitHub](http://github.com/caolan/async/downloads). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed + +__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped + + +## In the Browser + +So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + + + + + +## Documentation + +### Collections + +* [forEach](#forEach) +* [map](#map) +* [filter](#filter) +* [reject](#reject) +* [reduce](#reduce) +* [detect](#detect) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) + +### Flow Control + +* [series](#series) +* [parallel](#parallel) +* [whilst](#whilst) +* [until](#until) +* [waterfall](#waterfall) +* [queue](#queue) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) + +### Utils + +* [memoize](#memoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + +### forEach(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the forEach function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + + // assuming openFiles is an array of file names and saveFile is a function + // to save the modified contents of that file: + + async.forEach(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error + }); + +--------------------------------------- + + +### forEachSeries(arr, iterator, callback) + +The same as forEach only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + + async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file + }); + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + + async.filter(['file1','file2','file3'], path.exists, function(results){ + // results now equals an array of the existing files + }); + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as filter, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then its probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback which accepts an optional error as its first argument, and the state + of the reduction as the second. If an error is passed to the callback, the + reduction is stopped and the main callback is immediately called with the + error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + + async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); + }, function(err, result){ + // result is now equal to the last value of memo, which is 6 + }); + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + + async.detect(['file1','file2','file3'], path.exists, function(result){ + // result now equals the first file in the list that exists + }); + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and a value to use as the sort criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + + async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); + }, function(err, results){ + // results is now the original array of files sorted by + // modified date + }); + + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + + async.some(['file1','file2','file3'], path.exists, function(result){ + // if result is true then at least one of the files exists + }); + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like path.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + + async.every(['file1','file2','file3'], path.exists, function(result){ + // if result is true then every file exists + }); + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback which must be called once it has completed + with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + + async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories + }); + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Flow Control + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + }, + ], + // optional callback + function(err, results){ + // results is now equal to ['one', 'two'] + }); + + + // an example using an object instead of an array + async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed a + callback it must call on completion. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets an array of all the arguments passed to + the callbacks used in the array. + +__Example__ + + async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + }, + ], + // optional callback + function(err, results){ + // in this case, the results array will equal ['two','one'] + // because the functions were run in parallel and the second + // function had a shorter timeout before calling the callback. + }); + + + // an example using an object instead of an array + async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + }, + }, + function(err, results) { + // results is now equals to: {one: 1, two: 2} + }); + + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback which must be called once it has completed with an optional + error as the first argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + + var count = 0; + + async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } + }); + + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. +* callback(err) - An optional callback to run once all the functions have + completed. This function gets passed any error that may have occurred. + +__Example__ + + async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } + ]); + + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + + // create a queue object with concurrency 2 + + var q = async.queue(function (task, callback) { + console.log('hello ' + task.name). + callback(); + }, 2); + + + // assign a callback + q.drain = function() { + console.log('all items have been processed'); + } + + // add some items to the queue + + q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); + }); + q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); + }); + + +--------------------------------------- + + +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass and error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + syntax is easier to understand by looking at the example. +* callback(err) - An optional callback which is called when all the tasks have + been completed. The callback may receive an error as an argument. + +__Example__ + + async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }], + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + }] + }); + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + + async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } + ], + function(results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + email_link: ['write_file', function(callback){ + // once the file is written let's email a link to it... + } + ]); + }); + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. Its also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a callback it + must call on completion. + +__Example__ + + var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } + ]); + + node> var iterator2 = iterator(); + 'one' + node> var iterator3 = iterator2(); + 'two' + node> iterator3(); + 'three' + node> var nextfn = iterator2.next(); + node> nextfn(); + 'three' + + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other flow control functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + + // using apply + + async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), + ]); + + + // the same process without using apply + + async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + }, + ]); + +It's possible to pass any number of additional arguments when calling the +continuation: + + node> var fn = async.apply(sys.puts, 'one'); + node> fn('two', 'three'); + one + two + three + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setTimeout(callback, 0), +which means other higher priority events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + + var call_order = []; + async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two] + }); + call_order.push('one') + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + + var slow_fn = function (name, callback) { + // do something + callback(null, result); + }; + var fn = async.memoize(slow_fn); + + // fn can now be used as if it were slow_fn + fn('some name', function () { + // callback + }); + + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); + }; + + node> async.log(hello, 'world'); + 'hello world' + + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + + var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); + }; + + node> async.dir(hello, 'world'); + {hello: 'world'} + + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/node_modules/request/node_modules/form-data/node_modules/async/async.min.js.gzip b/node_modules/request/node_modules/form-data/node_modules/async/async.min.js.gzip new file mode 100644 index 0000000..e1c3294 Binary files /dev/null and b/node_modules/request/node_modules/form-data/node_modules/async/async.min.js.gzip differ diff --git a/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.css b/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.css new file mode 100644 index 0000000..274434a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.css @@ -0,0 +1,70 @@ +/*! + * Styles taken from qunit.css + */ + +h1#nodeunit-header, h1.nodeunit-header { + padding: 15px; + font-size: large; + background-color: #06b; + color: white; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; +} + +h1#nodeunit-header a { + color: white; +} + +h2#nodeunit-banner { + height: 2em; + border-bottom: 1px solid white; + background-color: #eee; + margin: 0; + font-family: 'trebuchet ms', verdana, arial; +} +h2#nodeunit-banner.pass { + background-color: green; +} +h2#nodeunit-banner.fail { + background-color: red; +} + +h2#nodeunit-userAgent, h2.nodeunit-userAgent { + padding: 10px; + background-color: #eee; + color: black; + margin: 0; + font-size: small; + font-weight: normal; + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} + +div#nodeunit-testrunner-toolbar { + background: #eee; + border-top: 1px solid black; + padding: 10px; + font-family: 'trebuchet ms', verdana, arial; + margin: 0; + font-size: 10pt; +} + +ol#nodeunit-tests { + font-family: 'trebuchet ms', verdana, arial; + font-size: 10pt; +} +ol#nodeunit-tests li strong { + cursor:pointer; +} +ol#nodeunit-tests .pass { + color: green; +} +ol#nodeunit-tests .fail { + color: red; +} + +p#nodeunit-testresult { + margin-left: 1em; + font-size: 10pt; + font-family: 'trebuchet ms', verdana, arial; +} diff --git a/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.js b/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.js new file mode 100644 index 0000000..5957184 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/deps/nodeunit.js @@ -0,0 +1,1966 @@ +/*! + * Nodeunit + * https://github.com/caolan/nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * json2.js + * http://www.JSON.org/json2.js + * Public Domain. + * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + */ +nodeunit = (function(){ +/* + http://www.JSON.org/json2.js + 2010-11-17 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +if (!this.JSON) { + this.JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? + '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ +.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') +.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') +.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); +var assert = this.assert = {}; +var types = {}; +var core = {}; +var nodeunit = {}; +var reporter = {}; +/*global setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root = this, + previous_async = root.async; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + else { + root.async = async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + //// cross-browser compatiblity functions //// + + var _forEach = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _forEach(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _forEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + var _indexOf = function (arr, item) { + if (arr.indexOf) { + return arr.indexOf(item); + } + for (var i = 0; i < arr.length; i += 1) { + if (arr[i] === item) { + return i; + } + } + return -1; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + async.nextTick = function (fn) { + if (typeof process === 'undefined' || !(process.nextTick)) { + setTimeout(fn, 0); + } + else { + process.nextTick(fn); + } + }; + + async.forEach = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + _forEach(arr, function (x) { + iterator(x, function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + } + }); + }); + }; + + async.forEachSeries = function (arr, iterator, callback) { + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed === arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEach].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.forEachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.forEachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.forEach(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args || null); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + q.process(); + }); + } + }, + length: function () { + return tasks.length; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + +}()); +(function(exports){ +/** + * This file is based on the node.js assert module, but with some small + * changes for browser-compatibility + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + */ + + +/** + * Added for browser compatibility + */ + +var _keys = function(obj){ + if(Object.keys) return Object.keys(obj); + var keys = []; + for(var k in obj){ + if(obj.hasOwnProperty(k)) keys.push(k); + } + return keys; +}; + + + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.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 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. + + +var pSlice = Array.prototype.slice; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = exports; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({message: message, actual: actual, expected: expected}) + +assert.AssertionError = function AssertionError (options) { + this.name = "AssertionError"; + this.message = options.message; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } +}; +// code from util.inherits in node +assert.AssertionError.super_ = Error; + + +// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call +// TODO: test what effect this may have +var ctor = function () { this.constructor = assert.AssertionError; }; +ctor.prototype = Error.prototype; +assert.AssertionError.prototype = new ctor(); + + +assert.AssertionError.prototype.toString = function() { + if (this.message) { + return [this.name+":", this.message].join(' '); + } else { + return [ this.name+":" + , JSON.stringify(this.expected ) + , this.operator + , JSON.stringify(this.actual) + ].join(" "); + } +}; + +// assert.AssertionError instanceof Error + +assert.AssertionError.__proto__ = Error.prototype; + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +assert.ok = function ok(value, message) { + if (!!!value) fail(value, true, message, "==", assert.ok); +}; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, "==", assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, "!=", assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, "deepEqual", assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isUndefinedOrNull (value) { + return value === null || value === undefined; +} + +function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try{ + var ka = _keys(a), + kb = _keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key] )) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, "===", assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as determined by !==. +// assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, "!==", assert.notStrictEqual); + } +}; + +function _throws (shouldThrow, block, err, message) { + var exception = null, + threw = false, + typematters = true; + + message = message || ""; + + //handle optional arguments + if (arguments.length == 3) { + if (typeof(err) == "string") { + message = err; + typematters = false; + } + } else if (arguments.length == 2) { + typematters = false; + } + + try { + block(); + } catch (e) { + threw = true; + exception = e; + } + + if (shouldThrow && !threw) { + fail( "Missing expected exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if (!shouldThrow && threw && typematters && exception instanceof err) { + fail( "Got unwanted exception" + + (err && err.name ? " ("+err.name+")." : '.') + + (message ? " " + message : "") + ); + } + if ((shouldThrow && threw && typematters && !(exception instanceof err)) || + (!shouldThrow && threw)) { + throw exception; + } +}; + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function (err) { if (err) {throw err;}}; +})(assert); +(function(exports){ +/*! + * Nodeunit + * Copyright (c) 2010 Caolan McMahon + * MIT Licensed + * + * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS! + * Only code on that line will be removed, its mostly to avoid requiring code + * that is node specific + */ + +/** + * Module dependencies + */ + + + +/** + * Creates assertion objects representing the result of an assert call. + * Accepts an object or AssertionError as its argument. + * + * @param {object} obj + * @api public + */ + +exports.assertion = function (obj) { + return { + method: obj.method || '', + message: obj.message || (obj.error && obj.error.message) || '', + error: obj.error, + passed: function () { + return !this.error; + }, + failed: function () { + return Boolean(this.error); + } + }; +}; + +/** + * Creates an assertion list object representing a group of assertions. + * Accepts an array of assertion objects. + * + * @param {Array} arr + * @param {Number} duration + * @api public + */ + +exports.assertionList = function (arr, duration) { + var that = arr || []; + that.failures = function () { + var failures = 0; + for (var i=0; i(' + + '' + assertions.failures() + ', ' + + '' + assertions.passes() + ', ' + + assertions.length + + ')'; + test.className = assertions.failures() ? 'fail': 'pass'; + test.appendChild(strong); + + var aList = document.createElement('ol'); + aList.style.display = 'none'; + test.onclick = function () { + var d = aList.style.display; + aList.style.display = (d == 'none') ? 'block': 'none'; + }; + for (var i=0; i' + (a.error.stack || a.error) + ''; + li.className = 'fail'; + } + else { + li.innerHTML = a.message || a.method || 'no message'; + li.className = 'pass'; + } + aList.appendChild(li); + } + test.appendChild(aList); + tests.appendChild(test); + }, + done: function (assertions) { + var end = new Date().getTime(); + var duration = end - start; + + var failures = assertions.failures(); + banner.className = failures ? 'fail': 'pass'; + + result.innerHTML = 'Tests completed in ' + duration + + ' milliseconds.
    ' + + assertions.passes() + ' assertions of ' + + '' + assertions.length + ' passed, ' + + assertions.failures() + ' failed.'; + } + }); +}; +})(reporter); +nodeunit = core; +nodeunit.assert = assert; +nodeunit.reporter = reporter; +nodeunit.run = reporter.run; +return nodeunit; })(); diff --git a/node_modules/request/node_modules/form-data/node_modules/async/dist/async.min.js b/node_modules/request/node_modules/form-data/node_modules/async/dist/async.min.js new file mode 100644 index 0000000..f89741e --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/dist/async.min.js @@ -0,0 +1 @@ +/*global setTimeout: false, console: false */(function(){var a={};var b=this,c=b.async;typeof module!=="undefined"&&module.exports?module.exports=a:b.async=a,a.noConflict=function(){b.async=c;return a};var d=function(a,b){if(a.forEach)return a.forEach(b);for(var c=0;cd?1:0};d(null,e(b.sort(c),function(a){return a.value}))})},a.auto=function(a,b){b=b||function(){};var c=g(a);if(!c.length)return b(null);var e=[];var i=[];var j=function(a){i.unshift(a)};var k=function(a){for(var b=0;b b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var completed = []; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _forEach(listeners, function (fn) { + fn(); + }); + }; + + addListener(function () { + if (completed.length === keys.length) { + callback(null); + } + }); + + _forEach(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + if (err) { + callback(err); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + completed.push(k); + taskComplete(); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && _indexOf(completed, x) !== -1); + }, true); + }; + if (ready()) { + task[task.length - 1](taskCallback); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + if (!tasks.length) { + return callback(); + } + callback = callback || function () {}; + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.nextTick(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + async.parallel = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEach(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.forEachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.queue = function (worker, concurrency) { + var workers = 0; + var tasks = []; + var q = { + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + tasks.push({data: data, callback: callback}); + if(q.saturated && tasks.length == concurrency) q.saturated(); + async.nextTick(q.process); + }, + process: function () { + if (workers < q.concurrency && tasks.length) { + var task = tasks.splice(0, 1)[0]; + if(q.empty && tasks.length == 0) q.empty(); + workers += 1; + worker(task.data, function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if(q.drain && tasks.length + workers == 0) q.drain(); + q.process(); + }); + } + }, + length: function () { + return tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _forEach(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + hasher = hasher || function (x) { + return x; + }; + return function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else { + fn.apply(null, args.concat([function () { + memo[key] = arguments; + callback.apply(null, arguments); + }])); + } + }; + }; + +}()); diff --git a/node_modules/request/node_modules/form-data/node_modules/async/nodelint.cfg b/node_modules/request/node_modules/form-data/node_modules/async/nodelint.cfg new file mode 100644 index 0000000..457a967 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/nodelint.cfg @@ -0,0 +1,4 @@ +var options = { + indent: 4, + onevar: false +}; diff --git a/node_modules/request/node_modules/form-data/node_modules/async/package.json b/node_modules/request/node_modules/form-data/node_modules/async/package.json new file mode 100644 index 0000000..e5646d7 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/package.json @@ -0,0 +1,41 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "main": "./index", + "author": { + "name": "Caolan McMahon" + }, + "version": "0.1.9", + "repository": { + "type": "git", + "url": "git://github.com/caolan/async.git" + }, + "bugs": { + "url": "http://github.com/caolan/async/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/caolan/async/raw/master/LICENSE" + } + ], + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "async@0.1.9", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "fd9b6aca66495fd0f7e97f86e71c7706ca9ae754" + }, + "_from": "async@0.1.9" +} diff --git a/node_modules/request/node_modules/form-data/node_modules/async/test/.swp b/node_modules/request/node_modules/form-data/node_modules/async/test/.swp new file mode 100644 index 0000000..ece9b6b Binary files /dev/null and b/node_modules/request/node_modules/form-data/node_modules/async/test/.swp differ diff --git a/node_modules/request/node_modules/form-data/node_modules/async/test/test-async.js b/node_modules/request/node_modules/form-data/node_modules/async/test/test-async.js new file mode 100644 index 0000000..8c2cebd --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/test/test-async.js @@ -0,0 +1,1367 @@ +var async = require('../lib/async'); + + +exports['auto'] = function(test){ + var callOrder = []; + var testdata = [{test: 'test'}]; + async.auto({ + task1: ['task2', function(callback){ + setTimeout(function(){ + callOrder.push('task1'); + callback(); + }, 25); + }], + task2: function(callback){ + setTimeout(function(){ + callOrder.push('task2'); + callback(); + }, 50); + }, + task3: ['task2', function(callback){ + callOrder.push('task3'); + callback(); + }], + task4: ['task1', 'task2', function(callback){ + callOrder.push('task4'); + callback(); + }] + }, + function(err){ + test.same(callOrder, ['task2','task3','task1','task4']); + test.done(); + }); +}; + +exports['auto empty object'] = function(test){ + async.auto({}, function(err){ + test.done(); + }); +}; + +exports['auto error'] = function(test){ + test.expect(1); + async.auto({ + task1: function(callback){ + callback('testerror'); + }, + task2: ['task1', function(callback){ + test.ok(false, 'task2 should not be called'); + callback(); + }], + task3: function(callback){ + callback('testerror2'); + } + }, + function(err){ + test.equals(err, 'testerror'); + }); + setTimeout(test.done, 100); +}; + +exports['auto no callback'] = function(test){ + async.auto({ + task1: function(callback){callback();}, + task2: ['task1', function(callback){callback(); test.done();}] + }); +}; + +exports['waterfall'] = function(test){ + test.expect(6); + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push('fn1'); + setTimeout(function(){callback(null, 'one', 'two');}, 0); + }, + function(arg1, arg2, callback){ + call_order.push('fn2'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25); + }, + function(arg1, arg2, arg3, callback){ + call_order.push('fn3'); + test.equals(arg1, 'one'); + test.equals(arg2, 'two'); + test.equals(arg3, 'three'); + callback(null, 'four'); + }, + function(arg4, callback){ + call_order.push('fn4'); + test.same(call_order, ['fn1','fn2','fn3','fn4']); + callback(null, 'test'); + } + ], function(err){ + test.done(); + }); +}; + +exports['waterfall empty array'] = function(test){ + async.waterfall([], function(err){ + test.done(); + }); +}; + +exports['waterfall no callback'] = function(test){ + async.waterfall([ + function(callback){callback();}, + function(callback){callback(); test.done();} + ]); +}; + +exports['waterfall async'] = function(test){ + var call_order = []; + async.waterfall([ + function(callback){ + call_order.push(1); + callback(); + call_order.push(2); + }, + function(callback){ + call_order.push(3); + callback(); + }, + function(){ + test.same(call_order, [1,2,3]); + test.done(); + } + ]); +}; + +exports['waterfall error'] = function(test){ + test.expect(1); + async.waterfall([ + function(callback){ + callback('error'); + }, + function(callback){ + test.ok(false, 'next function should not be called'); + callback(); + } + ], function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['waterfall multiple callback calls'] = function(test){ + var call_order = []; + var arr = [ + function(callback){ + call_order.push(1); + // call the callback twice. this should call function 2 twice + callback(null, 'one', 'two'); + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + call_order.push(2); + callback(null, arg1, arg2, 'three'); + }, + function(arg1, arg2, arg3, callback){ + call_order.push(3); + callback(null, 'four'); + }, + function(arg4){ + call_order.push(4); + arr[3] = function(){ + call_order.push(4); + test.same(call_order, [1,2,2,3,3,4,4]); + test.done(); + }; + } + ]; + async.waterfall(arr); +}; + + +exports['parallel'] = function(test){ + var call_order = []; + async.parallel([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, [1,2,[3,3]]); + test.done(); + }); +}; + +exports['parallel empty array'] = function(test){ + async.parallel([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['parallel error'] = function(test){ + async.parallel([ + function(callback){ + callback('error', 1); + }, + function(callback){ + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['parallel no callback'] = function(test){ + async.parallel([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['parallel object'] = function(test){ + var call_order = []; + async.parallel({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(call_order, [3,1,2]); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.done(); + }); +}; + +exports['series'] = function(test){ + var call_order = []; + async.series([ + function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + ], + function(err, results){ + test.equals(err, null); + test.same(results, [1,2,[3,3]]); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['series empty array'] = function(test){ + async.series([], function(err, results){ + test.equals(err, null); + test.same(results, []); + test.done(); + }); +}; + +exports['series error'] = function(test){ + test.expect(1); + async.series([ + function(callback){ + callback('error', 1); + }, + function(callback){ + test.ok(false, 'should not be called'); + callback('error2', 2); + } + ], + function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 100); +}; + +exports['series no callback'] = function(test){ + async.series([ + function(callback){callback();}, + function(callback){callback(); test.done();}, + ]); +}; + +exports['series object'] = function(test){ + var call_order = []; + async.series({ + one: function(callback){ + setTimeout(function(){ + call_order.push(1); + callback(null, 1); + }, 25); + }, + two: function(callback){ + setTimeout(function(){ + call_order.push(2); + callback(null, 2); + }, 50); + }, + three: function(callback){ + setTimeout(function(){ + call_order.push(3); + callback(null, 3,3); + }, 15); + } + }, + function(err, results){ + test.equals(err, null); + test.same(results, { + one: 1, + two: 2, + three: [3,3] + }); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['iterator'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + iterator(); + test.same(call_order, [1]); + var iterator2 = iterator(); + test.same(call_order, [1,1]); + var iterator3 = iterator2('arg1'); + test.same(call_order, [1,1,2]); + var iterator4 = iterator3('arg1', 'arg2'); + test.same(call_order, [1,1,2,3]); + test.equals(iterator4, undefined); + test.done(); +}; + +exports['iterator empty array'] = function(test){ + var iterator = async.iterator([]); + test.equals(iterator(), undefined); + test.equals(iterator.next(), undefined); + test.done(); +}; + +exports['iterator.next'] = function(test){ + var call_order = []; + var iterator = async.iterator([ + function(){call_order.push(1);}, + function(arg1){ + test.equals(arg1, 'arg1'); + call_order.push(2); + }, + function(arg1, arg2){ + test.equals(arg1, 'arg1'); + test.equals(arg2, 'arg2'); + call_order.push(3); + } + ]); + var fn = iterator.next(); + var iterator2 = fn('arg1'); + test.same(call_order, [2]); + iterator2('arg1','arg2'); + test.same(call_order, [2,3]); + test.equals(iterator2.next(), undefined); + test.done(); +}; + +exports['forEach'] = function(test){ + var args = []; + async.forEach([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,2,3]); + test.done(); + }); +}; + +exports['forEach empty array'] = function(test){ + test.expect(1); + async.forEach([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEach error'] = function(test){ + test.expect(1); + async.forEach([1,2,3], function(x, callback){ + callback('error'); + }, function(err){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['forEachSeries'] = function(test){ + var args = []; + async.forEachSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + args.push(x); + callback(); + }, x*25); + }, function(err){ + test.same(args, [1,3,2]); + test.done(); + }); +}; + +exports['forEachSeries empty array'] = function(test){ + test.expect(1); + async.forEachSeries([], function(x, callback){ + test.ok(false, 'iterator should not be called'); + callback(); + }, function(err){ + test.ok(true, 'should call callback'); + }); + setTimeout(test.done, 25); +}; + +exports['forEachSeries error'] = function(test){ + test.expect(2); + var call_order = []; + async.forEachSeries([1,2,3], function(x, callback){ + call_order.push(x); + callback('error'); + }, function(err){ + test.same(call_order, [1]); + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['map'] = function(test){ + var call_order = []; + async.map([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,2,3]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['map original untouched'] = function(test){ + var a = [1,2,3]; + async.map(a, function(x, callback){ + callback(null, x*2); + }, function(err, results){ + test.same(results, [2,4,6]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['map error'] = function(test){ + test.expect(1); + async.map([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['mapSeries'] = function(test){ + var call_order = []; + async.mapSeries([1,3,2], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(null, x*2); + }, x*25); + }, function(err, results){ + test.same(call_order, [1,3,2]); + test.same(results, [2,6,4]); + test.done(); + }); +}; + +exports['mapSeries error'] = function(test){ + test.expect(1); + async.mapSeries([1,2,3], function(x, callback){ + callback('error'); + }, function(err, results){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['reduce'] = function(test){ + var call_order = []; + async.reduce([1,2,3], 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [1,2,3]); + test.done(); + }); +}; + +exports['reduce async with non-reference memo'] = function(test){ + async.reduce([1,3,2], 0, function(a, x, callback){ + setTimeout(function(){callback(null, a + x)}, Math.random()*100); + }, function(err, result){ + test.equals(result, 6); + test.done(); + }); +}; + +exports['reduce error'] = function(test){ + test.expect(1); + async.reduce([1,2,3], 0, function(a, x, callback){ + callback('error'); + }, function(err, result){ + test.equals(err, 'error'); + }); + setTimeout(test.done, 50); +}; + +exports['inject alias'] = function(test){ + test.equals(async.inject, async.reduce); + test.done(); +}; + +exports['foldl alias'] = function(test){ + test.equals(async.foldl, async.reduce); + test.done(); +}; + +exports['reduceRight'] = function(test){ + var call_order = []; + var a = [1,2,3]; + async.reduceRight(a, 0, function(a, x, callback){ + call_order.push(x); + callback(null, a + x); + }, function(err, result){ + test.equals(result, 6); + test.same(call_order, [3,2,1]); + test.same(a, [1,2,3]); + test.done(); + }); +}; + +exports['foldr alias'] = function(test){ + test.equals(async.foldr, async.reduceRight); + test.done(); +}; + +exports['filter'] = function(test){ + async.filter([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['filter original untouched'] = function(test){ + var a = [3,1,2]; + async.filter(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [3,1]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['filterSeries'] = function(test){ + async.filterSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [3,1]); + test.done(); + }); +}; + +exports['select alias'] = function(test){ + test.equals(async.select, async.filter); + test.done(); +}; + +exports['selectSeries alias'] = function(test){ + test.equals(async.selectSeries, async.filterSeries); + test.done(); +}; + +exports['reject'] = function(test){ + async.reject([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['reject original untouched'] = function(test){ + var a = [3,1,2]; + async.reject(a, function(x, callback){ + callback(x % 2); + }, function(results){ + test.same(results, [2]); + test.same(a, [3,1,2]); + test.done(); + }); +}; + +exports['rejectSeries'] = function(test){ + async.rejectSeries([3,1,2], function(x, callback){ + setTimeout(function(){callback(x % 2);}, x*25); + }, function(results){ + test.same(results, [2]); + test.done(); + }); +}; + +exports['some true'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 1);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['some false'] = function(test){ + async.some([3,1,2], function(x, callback){ + setTimeout(function(){callback(x === 10);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['some early return'] = function(test){ + var call_order = []; + async.some([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,'callback',2,3]); + test.done(); + }, 100); +}; + +exports['any alias'] = function(test){ + test.equals(async.any, async.some); + test.done(); +}; + +exports['every true'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(true);}, 0); + }, function(result){ + test.equals(result, true); + test.done(); + }); +}; + +exports['every false'] = function(test){ + async.every([1,2,3], function(x, callback){ + setTimeout(function(){callback(x % 2);}, 0); + }, function(result){ + test.equals(result, false); + test.done(); + }); +}; + +exports['every early return'] = function(test){ + var call_order = []; + async.every([1,2,3], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x === 1); + }, x*25); + }, function(result){ + call_order.push('callback'); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['all alias'] = function(test){ + test.equals(async.all, async.every); + test.done(); +}; + +exports['detect'] = function(test){ + var call_order = []; + async.detect([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [1,2,'callback',3]); + test.done(); + }, 100); +}; + +exports['detectSeries'] = function(test){ + var call_order = []; + async.detectSeries([3,2,1], function(x, callback){ + setTimeout(function(){ + call_order.push(x); + callback(x == 2); + }, x*25); + }, function(result){ + call_order.push('callback'); + test.equals(result, 2); + }); + setTimeout(function(){ + test.same(call_order, [3,2,'callback']); + test.done(); + }, 200); +}; + +exports['sortBy'] = function(test){ + async.sortBy([{a:1},{a:15},{a:6}], function(x, callback){ + setTimeout(function(){callback(null, x.a);}, 0); + }, function(err, result){ + test.same(result, [{a:1},{a:6},{a:15}]); + test.done(); + }); +}; + +exports['apply'] = function(test){ + test.expect(6); + var fn = function(){ + test.same(Array.prototype.slice.call(arguments), [1,2,3,4]) + }; + async.apply(fn, 1, 2, 3, 4)(); + async.apply(fn, 1, 2, 3)(4); + async.apply(fn, 1, 2)(3, 4); + async.apply(fn, 1)(2, 3, 4); + async.apply(fn)(1, 2, 3, 4); + test.equals( + async.apply(function(name){return 'hello ' + name}, 'world')(), + 'hello world' + ); + test.done(); +}; + + +// generates tests for console functions such as async.log +var console_fn_tests = function(name){ + + if (typeof console !== 'undefined') { + exports[name] = function(test){ + test.expect(5); + var fn = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback(null, 'test');}, 0); + }; + var fn_err = function(arg1, callback){ + test.equals(arg1, 'one'); + setTimeout(function(){callback('error');}, 0); + }; + var _console_fn = console[name]; + var _error = console.error; + console[name] = function(val){ + test.equals(val, 'test'); + test.equals(arguments.length, 1); + console.error = function(val){ + test.equals(val, 'error'); + console[name] = _console_fn; + console.error = _error; + test.done(); + }; + async[name](fn_err, 'one'); + }; + async[name](fn, 'one'); + }; + + exports[name + ' with multiple result params'] = function(test){ + var fn = function(callback){callback(null,'one','two','three');}; + var _console_fn = console[name]; + var called_with = []; + console[name] = function(x){ + called_with.push(x); + }; + async[name](fn); + test.same(called_with, ['one','two','three']); + console[name] = _console_fn; + test.done(); + }; + } + + // browser-only test + exports[name + ' without console.' + name] = function(test){ + if (typeof window !== 'undefined') { + var _console = window.console; + window.console = undefined; + var fn = function(callback){callback(null, 'val');}; + var fn_err = function(callback){callback('error');}; + async[name](fn); + async[name](fn_err); + window.console = _console; + } + test.done(); + }; + +}; + +console_fn_tests('log'); +console_fn_tests('dir'); +/*console_fn_tests('info'); +console_fn_tests('warn'); +console_fn_tests('error');*/ + +exports['nextTick'] = function(test){ + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + call_order.push('one'); + setTimeout(function(){ + test.same(call_order, ['one','two']); + test.done(); + }, 50); +}; + +exports['nextTick in the browser'] = function(test){ + if (typeof process !== 'undefined') { + // skip this test in node + return test.done(); + } + test.expect(1); + + var call_order = []; + async.nextTick(function(){call_order.push('two');}); + + call_order.push('one'); + setTimeout(function(){ + if (typeof process !== 'undefined') { + process.nextTick = _nextTick; + } + test.same(call_order, ['one','two']); + }, 50); + setTimeout(test.done, 100); +}; + +exports['noConflict - node only'] = function(test){ + if (typeof process !== 'undefined') { + // node only test + test.expect(3); + var fs = require('fs'); + var filename = __dirname + '/../lib/async.js'; + fs.readFile(filename, function(err, content){ + if(err) return test.done(); + var Script = process.binding('evals').Script; + + var s = new Script(content, filename); + var s2 = new Script( + content + 'this.async2 = this.async.noConflict();', + filename + ); + + var sandbox1 = {async: 'oldvalue'}; + s.runInNewContext(sandbox1); + test.ok(sandbox1.async); + + var sandbox2 = {async: 'oldvalue'}; + s2.runInNewContext(sandbox2); + test.equals(sandbox2.async, 'oldvalue'); + test.ok(sandbox2.async2); + + test.done(); + }); + } + else test.done(); +}; + +exports['concat'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concat([1,3,2], iterator, function(err, results){ + test.same(results, [1,2,1,3,2,1]); + test.same(call_order, [1,2,3]); + test.ok(!err); + test.done(); + }); +}; + +exports['concat error'] = function(test){ + var iterator = function (x, cb) { + cb(new Error('test error')); + }; + async.concat([1,2,3], iterator, function(err, results){ + test.ok(err); + test.done(); + }); +}; + +exports['concatSeries'] = function(test){ + var call_order = []; + var iterator = function (x, cb) { + setTimeout(function(){ + call_order.push(x); + var r = []; + while (x > 0) { + r.push(x); + x--; + } + cb(null, r); + }, x*25); + }; + async.concatSeries([1,3,2], iterator, function(err, results){ + test.same(results, [1,3,2,1,2,1]); + test.same(call_order, [1,3,2]); + test.ok(!err); + test.done(); + }); +}; + +exports['until'] = function (test) { + var call_order = []; + + var count = 0; + async.until( + function () { + call_order.push(['test', count]); + return (count == 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['whilst'] = function (test) { + var call_order = []; + + var count = 0; + async.whilst( + function () { + call_order.push(['test', count]); + return (count < 5); + }, + function (cb) { + call_order.push(['iterator', count]); + count++; + cb(); + }, + function (err) { + test.same(call_order, [ + ['test', 0], + ['iterator', 0], ['test', 1], + ['iterator', 1], ['test', 2], + ['iterator', 2], ['test', 3], + ['iterator', 3], ['test', 4], + ['iterator', 4], ['test', 5], + ]); + test.equals(count, 5); + test.done(); + } + ); +}; + +exports['queue'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', 'callback 2', + 'process 1', 'callback 1', + 'process 4', 'callback 4', + 'process 3', 'callback 3' + ]); + test.equal(q.concurrency, 2); + test.equal(q.length(), 0); + test.done(); + }, 200); +}; + +exports['queue changing concurrency'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-2---3-4 + // order of completion: 1,2,3,4 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 3); + call_order.push('callback ' + 1); + }); + q.push(2, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 2); + call_order.push('callback ' + 2); + }); + q.push(3, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 1); + call_order.push('callback ' + 3); + }); + q.push(4, function (err, arg) { + test.equal(err, 'error'); + test.equal(arg, 'arg'); + test.equal(q.length(), 0); + call_order.push('callback ' + 4); + }); + test.equal(q.length(), 4); + test.equal(q.concurrency, 2); + q.concurrency = 1; + + setTimeout(function () { + test.same(call_order, [ + 'process 1', 'callback 1', + 'process 2', 'callback 2', + 'process 3', 'callback 3', + 'process 4', 'callback 4' + ]); + test.equal(q.concurrency, 1); + test.equal(q.length(), 0); + test.done(); + }, 250); +}; + +exports['queue push without callback'] = function (test) { + var call_order = [], + delays = [40,20,60,20]; + + // worker1: --1-4 + // worker2: -2---3 + // order of completion: 2,1,4,3 + + var q = async.queue(function (task, callback) { + setTimeout(function () { + call_order.push('process ' + task); + callback('error', 'arg'); + }, delays.splice(0,1)[0]); + }, 2); + + q.push(1); + q.push(2); + q.push(3); + q.push(4); + + setTimeout(function () { + test.same(call_order, [ + 'process 2', + 'process 1', + 'process 4', + 'process 3' + ]); + test.done(); + }, 200); +}; + +exports['memoize'] = function (test) { + test.expect(4); + var call_order = []; + + var fn = function (arg1, arg2, callback) { + call_order.push(['fn', arg1, arg2]); + callback(null, arg1 + arg2); + }; + + var fn2 = async.memoize(fn); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 4); + }); + + test.same(call_order, [['fn',1,2], ['fn',2,2]]); + test.done(); +}; + +exports['memoize error'] = function (test) { + test.expect(1); + var testerr = new Error('test'); + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + async.memoize(fn)(1, 2, function (err, result) { + test.equal(err, testerr); + }); + test.done(); +}; + +exports['memoize custom hash function'] = function (test) { + test.expect(2); + var testerr = new Error('test'); + + var fn = function (arg1, arg2, callback) { + callback(testerr, arg1 + arg2); + }; + var fn2 = async.memoize(fn, function () { + return 'custom hash'; + }); + fn2(1, 2, function (err, result) { + test.equal(result, 3); + }); + fn2(2, 2, function (err, result) { + test.equal(result, 3); + }); + test.done(); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in series'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.series( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.same(results, [false, undefined, undefined, null]); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +// Issue 10 on github: https://github.com/caolan/async/issues#issue/10 +exports['falsy return values in parallel'] = function (test) { + function taskFalse(callback) { + async.nextTick(function() { + callback(null, false); + }); + }; + function taskUndefined(callback) { + async.nextTick(function() { + callback(null, undefined); + }); + }; + function taskEmpty(callback) { + async.nextTick(function() { + callback(null); + }); + }; + function taskNull(callback) { + async.nextTick(function() { + callback(null, null); + }); + }; + async.parallel( + [taskFalse, taskUndefined, taskEmpty, taskNull], + function(err, results) { + test.same(results, [false, undefined, undefined, null]); + test.strictEqual(results[0], false); + test.strictEqual(results[1], undefined); + test.strictEqual(results[2], undefined); + test.strictEqual(results[3], null); + test.done(); + } + ); +}; + +exports['queue events'] = function(test) { + var calls = []; + var q = async.queue(function(task, cb) { + // nop + calls.push('process ' + task); + cb(); + }, 3); + + q.saturated = function() { + test.ok(q.length() == 3, 'queue should be saturated now'); + calls.push('saturated'); + }; + q.empty = function() { + test.ok(q.length() == 0, 'queue should be empty now'); + calls.push('empty'); + }; + q.drain = function() { + test.ok( + q.length() == 0 && q.running() == 0, + 'queue should be empty now and no more workers should be running' + ); + calls.push('drain'); + test.same(calls, [ + 'saturated', + 'process foo', + 'foo cb', + 'process bar', + 'bar cb', + 'process zoo', + 'zoo cb', + 'process poo', + 'poo cb', + 'empty', + 'process moo', + 'moo cb', + 'drain', + ]); + test.done(); + }; + q.push('foo', function () {calls.push('foo cb');}); + q.push('bar', function () {calls.push('bar cb');}); + q.push('zoo', function () {calls.push('zoo cb');}); + q.push('poo', function () {calls.push('poo cb');}); + q.push('moo', function () {calls.push('moo cb');}); +}; diff --git a/node_modules/request/node_modules/form-data/node_modules/async/test/test.html b/node_modules/request/node_modules/form-data/node_modules/async/test/test.html new file mode 100644 index 0000000..2450e2d --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/async/test/test.html @@ -0,0 +1,24 @@ + + + Async.js Test Suite + + + + + + + + +

    Async.js Test Suite

    + + + diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore b/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore new file mode 100644 index 0000000..aba34f0 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore @@ -0,0 +1,3 @@ +*.un~ +/node_modules +/test/tmp diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/License b/node_modules/request/node_modules/form-data/node_modules/combined-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +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. diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile b/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md b/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md new file mode 100644 index 0000000..1a9999e --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md @@ -0,0 +1,132 @@ +# combined-stream + +A stream that emits multiple other streams one after another. + +## Installation + +``` bash +npm install combined-stream +``` + +## Usage + +Here is a simple example that shows how you can use combined-stream to combine +two files into one: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +While the example above works great, it will pause all source streams until +they are needed. If you don't want that to happen, you can set `pauseStreams` +to `false`: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create({pauseStreams: false}); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +However, what if you don't have all the source streams yet, or you don't want +to allocate the resources (file descriptors, memory, etc.) for them right away? +Well, in that case you can simply provide a callback that supplies the stream +by calling a `next()` function: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(function(next) { + next(fs.createReadStream('file1.txt')); +}); +combinedStream.append(function(next) { + next(fs.createReadStream('file2.txt')); +}); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +## API + +### CombinedStream.create([options]) + +Returns a new combined stream object. Available options are: + +* `maxDataSize` +* `pauseStreams` + +The effect of those options is described below. + +### combinedStream.pauseStreams = true + +Whether to apply back pressure to the underlaying streams. If set to `false`, +the underlaying streams will never be paused. If set to `true`, the +underlaying streams will be paused right after being appended, as well as when +`delayedStream.pipe()` wants to throttle. + +### combinedStream.maxDataSize = 2 * 1024 * 1024 + +The maximum amount of bytes (or characters) to buffer for all source streams. +If this value is exceeded, `combinedStream` emits an `'error'` event. + +### combinedStream.dataSize = 0 + +The amount of bytes (or characters) currently buffered by `combinedStream`. + +### combinedStream.append(stream) + +Appends the given `stream` to the combinedStream object. If `pauseStreams` is +set to `true, this stream will also be paused right away. + +`streams` can also be a function that takes one parameter called `next`. `next` +is a function that must be invoked in order to provide the `next` stream, see +example above. + +Regardless of how the `stream` is appended, combined-stream always attaches an +`'error'` listener to it, so you don't have to do that manually. + +Special case: `stream` can also be a String or Buffer. + +### combinedStream.write(data) + +You should not call this, `combinedStream` takes care of piping the appended +streams into itself for you. + +### combinedStream.resume() + +Causes `combinedStream` to start drain the streams it manages. The function is +idempotent, and also emits a `'resume'` event each time which usually goes to +the stream that is currently being drained. + +### combinedStream.pause(); + +If `combinedStream.pauseStreams` is set to `false`, this does nothing. +Otherwise a `'pause'` event is emitted, this goes to the stream that is +currently being drained, so you can use it to apply back pressure. + +### combinedStream.end(); + +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes +all streams from the queue. + +### combinedStream.destroy(); + +Same as `combinedStream.end()`, except it emits a `'close'` event instead of +`'end'`. + +## License + +combined-stream is licensed under the MIT license. diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js new file mode 100644 index 0000000..03754e6 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js @@ -0,0 +1,183 @@ +var util = require('util'); +var Stream = require('stream').Stream; +var DelayedStream = require('delayed-stream'); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + stream.on('data', this._checkDataSize.bind(this)); + + stream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + var stream = this._streams.shift(); + + + if (!stream) { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)) + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore new file mode 100644 index 0000000..2fedb26 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore @@ -0,0 +1,2 @@ +*.un~ +/node_modules/* diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited + +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. diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md new file mode 100644 index 0000000..5cb5b35 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md @@ -0,0 +1,154 @@ +# delayed-stream + +Buffers events from a stream until you are ready to handle them. + +## Installation + +``` bash +npm install delayed-stream +``` + +## Usage + +The following example shows how to write a http echo server that delays its +response by 1000 ms. + +``` javascript +var DelayedStream = require('delayed-stream'); +var http = require('http'); + +http.createServer(function(req, res) { + var delayed = DelayedStream.create(req); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 1000); +}); +``` + +If you are not using `Stream#pipe`, you can also manually release the buffered +events by calling `delayedStream.resume()`: + +``` javascript +var delayed = DelayedStream.create(req); + +setTimeout(function() { + // Emit all buffered events and resume underlaying source + delayed.resume(); +}, 1000); +``` + +## Implementation + +In order to use this meta stream properly, here are a few things you should +know about the implementation. + +### Event Buffering / Proxying + +All events of the `source` stream are hijacked by overwriting the `source.emit` +method. Until node implements a catch-all event listener, this is the only way. + +However, delayed-stream still continues to emit all events it captures on the +`source`, regardless of whether you have released the delayed stream yet or +not. + +Upon creation, delayed-stream captures all `source` events and stores them in +an internal event buffer. Once `delayedStream.release()` is called, all +buffered events are emitted on the `delayedStream`, and the event buffer is +cleared. After that, delayed-stream merely acts as a proxy for the underlaying +source. + +### Error handling + +Error events on `source` are buffered / proxied just like any other events. +However, `delayedStream.create` attaches a no-op `'error'` listener to the +`source`. This way you only have to handle errors on the `delayedStream` +object, rather than in two places. + +### Buffer limits + +delayed-stream provides a `maxDataSize` property that can be used to limit +the amount of data being buffered. In order to protect you from bad `source` +streams that don't react to `source.pause()`, this feature is enabled by +default. + +## API + +### DelayedStream.create(source, [options]) + +Returns a new `delayedStream`. Available options are: + +* `pauseStream` +* `maxDataSize` + +The description for those properties can be found below. + +### delayedStream.source + +The `source` stream managed by this object. This is useful if you are +passing your `delayedStream` around, and you still want to access properties +on the `source` object. + +### delayedStream.pauseStream = true + +Whether to pause the underlaying `source` when calling +`DelayedStream.create()`. Modifying this property afterwards has no effect. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. You can also modify this property during runtime. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. + +### delayedStream.dataSize = 0 + +The amount of data buffered so far. + +### delayedStream.readable + +An ECMA5 getter that returns the value of `source.readable`. + +### delayedStream.resume() + +If the `delayedStream` has not been released so far, `delayedStream.release()` +is called. + +In either case, `source.resume()` is called. + +### delayedStream.pause() + +Calls `source.pause()`. + +### delayedStream.pipe(dest) + +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`. + +### delayedStream.release() + +Emits and clears all events that have been buffered up so far. This does not +resume the underlaying source, use `delayedStream.resume()` instead. + +## License + +delayed-stream is licensed under the MIT license. diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js new file mode 100644 index 0000000..7c10d48 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js @@ -0,0 +1,99 @@ +var Stream = require('stream').Stream; +var util = require('util'); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +DelayedStream.prototype.__defineGetter__('readable', function() { + return this.source.readable; +}); + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json new file mode 100644 index 0000000..d394b92 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json @@ -0,0 +1,38 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "delayed-stream", + "description": "Buffers events from a stream until you are ready to handle them.", + "version": "0.0.5", + "homepage": "https://github.com/felixge/node-delayed-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-delayed-stream.git" + }, + "main": "./lib/delayed_stream", + "engines": { + "node": ">=0.4.0" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "far": "0.0.1" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "delayed-stream@0.0.5", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "56f46a53506f656e1a549c63d8794c6cf8b6e1fc" + }, + "_from": "delayed-stream@0.0.5" +} diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js new file mode 100644 index 0000000..4d71b8a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js @@ -0,0 +1,6 @@ +var common = module.exports; + +common.DelayedStream = require('..'); +common.assert = require('assert'); +common.fake = require('fake'); +common.PORT = 49252; diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js new file mode 100644 index 0000000..9ecad5b --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var DelayedStream = common.DelayedStream; +var http = require('http'); + +var UPLOAD = new Buffer(10 * 1024 * 1024); + +var server = http.createServer(function(req, res) { + var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length}); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 10); +}); +server.listen(common.PORT, function() { + var request = http.request({ + method: 'POST', + port: common.PORT, + }); + + request.write(UPLOAD); + request.end(); + + request.on('response', function(res) { + var received = 0; + res + .on('data', function(chunk) { + received += chunk.length; + }) + .on('end', function() { + assert.equal(received, UPLOAD.length); + server.close(); + }); + }); +}); + + diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js new file mode 100644 index 0000000..6f417f3 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js @@ -0,0 +1,21 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testAutoPause() { + var source = new Stream(); + + fake.expect(source, 'pause', 1); + var delayedStream = DelayedStream.create(source); + fake.verify(); +})(); + +(function testDisableAutoPause() { + var source = new Stream(); + fake.expect(source, 'pause', 0); + + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + fake.verify(); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js new file mode 100644 index 0000000..b50c397 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js @@ -0,0 +1,14 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(source, 'pause'); + delayedStream.pause(); + fake.verify(); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js new file mode 100644 index 0000000..fc4047e --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js @@ -0,0 +1,48 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testDelayEventsUntilResume() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // delayedStream must not emit until we resume + fake.expect(delayedStream, 'emit', 0); + + // but our original source must emit + var params = []; + source.on('foo', function(param) { + params.push(param); + }); + + source.emit('foo', 1); + source.emit('foo', 2); + + // Make sure delayedStream did not emit, and source did + assert.deepEqual(params, [1, 2]); + fake.verify(); + + // After resume, delayedStream must playback all events + fake + .stub(delayedStream, 'emit') + .times(Infinity) + .withArg(1, 'newListener'); + fake.expect(delayedStream, 'emit', ['foo', 1]); + fake.expect(delayedStream, 'emit', ['foo', 2]); + fake.expect(source, 'resume'); + + delayedStream.resume(); + fake.verify(); + + // Calling resume again will delegate to source + fake.expect(source, 'resume'); + delayedStream.resume(); + fake.verify(); + + // Emitting more events directly leads to them being emitted + fake.expect(delayedStream, 'emit', ['foo', 3]); + source.emit('foo', 3); + fake.verify(); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js new file mode 100644 index 0000000..a9d35e7 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js @@ -0,0 +1,15 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testHandleSourceErrors() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + // We deal with this by attaching a no-op listener to 'error' on the source + // when creating a new DelayedStream. This way error events on the source + // won't throw. + source.emit('error', new Error('something went wrong')); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js new file mode 100644 index 0000000..7638a2b --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testMaxDataSize() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false}); + + source.emit('data', new Buffer(1024)); + + fake + .expect(delayedStream, 'emit') + .withArg(1, 'error'); + source.emit('data', new Buffer(1)); + fake.verify(); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js new file mode 100644 index 0000000..7d312ab --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testPipeReleases() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + fake.expect(delayedStream, 'resume'); + delayedStream.pipe(new Stream()); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js new file mode 100644 index 0000000..d436163 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js @@ -0,0 +1,13 @@ +var common = require('../common'); +var assert = common.assert; +var fake = common.fake.create(); +var DelayedStream = common.DelayedStream; +var Stream = require('stream').Stream; + +(function testProxyReadableProperty() { + var source = new Stream(); + var delayedStream = DelayedStream.create(source, {pauseStream: false}); + + source.readable = fake.value('source.readable'); + assert.strictEqual(delayedStream.readable, source.readable); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json b/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json new file mode 100644 index 0000000..7bb0fcf --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json @@ -0,0 +1,39 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "combined-stream", + "description": "A stream that emits multiple other streams one after another.", + "version": "0.0.3", + "homepage": "https://github.com/felixge/node-combined-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-combined-stream.git" + }, + "main": "./lib/combined_stream", + "engines": { + "node": "*" + }, + "dependencies": { + "delayed-stream": "0.0.5" + }, + "devDependencies": { + "far": "0.0.1" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "combined-stream@0.0.3", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "c41c9899277b587901bb6ce4bf458b94693afafa" + }, + "_from": "combined-stream@0.0.3" +} diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js new file mode 100644 index 0000000..aa9ab3a --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js @@ -0,0 +1,12 @@ +var common = module.exports; + +var path = require('path'); +var root = path.join(__dirname, '..'); + +common.dir = { + fixture: root + '/test/fixture', + tmp: root + '/test/tmp', +}; + +common.CombinedStream = require(root); +common.assert = require('assert'); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt new file mode 100644 index 0000000..50e0218 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt @@ -0,0 +1,256 @@ +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 +10101010101010101010101010101010101010101010101010101010101010101010101010101010 +01010101010101010101010101010101010101010101010101010101010101010101010101010101 diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt new file mode 100644 index 0000000..da1d821 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt @@ -0,0 +1,256 @@ +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 +20202020202020202020202020202020202020202020202020202020202020202020202020202020 +02020202020202020202020202020202020202020202020202020202020202020202020202020202 diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js new file mode 100644 index 0000000..44ecaba --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js @@ -0,0 +1,27 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE1)); + }); + combinedStream.append(function(next) { + next(fs.createReadStream(FILE2)); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js new file mode 100644 index 0000000..e3fbd18 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js @@ -0,0 +1,34 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; + +(function testDataSizeGetter() { + var combinedStream = CombinedStream.create(); + + assert.strictEqual(combinedStream.dataSize, 0); + + // Test one stream + combinedStream._streams.push({dataSize: 10}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 10); + + // Test two streams + combinedStream._streams.push({dataSize: 23}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test currentStream + combinedStream._currentStream = {dataSize: 20}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 53); + + // Test currentStream without dataSize + combinedStream._currentStream = {}; + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); + + // Test stream function + combinedStream._streams.push(function() {}); + combinedStream._updateDataSize(); + assert.strictEqual(combinedStream.dataSize, 33); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js new file mode 100644 index 0000000..c678575 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js @@ -0,0 +1,38 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var BUFFER = new Buffer('Bacon is delicious'); +var FILE2 = common.dir.fixture + '/file2.txt'; +var STRING = 'The € kicks the $\'s ass!'; + +var EXPECTED = + fs.readFileSync(FILE1) + + BUFFER + + fs.readFileSync(FILE2) + + STRING; +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(BUFFER); + combinedStream.append(fs.createReadStream(FILE2)); + combinedStream.append(function(next) { + next(STRING); + }); + + var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js new file mode 100644 index 0000000..263cfdf --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js @@ -0,0 +1,35 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); +var GOT; + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create(); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.equal(stream2.dataSize, 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('close', function() { + GOT = fs.readFileSync(tmpFile, 'utf8'); + }); +})(); + +process.on('exit', function() { + console.error(GOT.length, EXPECTED.length); + assert.strictEqual(GOT, EXPECTED); +}); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js new file mode 100644 index 0000000..25f47a4 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js @@ -0,0 +1,24 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var gotErr = null; + combinedStream.on('error', function(err) { + gotErr = err; + }); + + process.on('exit', function() { + assert.ok(gotErr); + assert.ok(gotErr.message.match(/bytes/)); + }); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js new file mode 100644 index 0000000..30a3a6f --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js @@ -0,0 +1,30 @@ +var common = require('../common'); +var assert = common.assert; +var CombinedStream = common.CombinedStream; +var fs = require('fs'); + +var FILE1 = common.dir.fixture + '/file1.txt'; +var FILE2 = common.dir.fixture + '/file2.txt'; +var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2); + +(function testDelayedStreams() { + var combinedStream = CombinedStream.create({pauseStreams: false}); + combinedStream.append(fs.createReadStream(FILE1)); + combinedStream.append(fs.createReadStream(FILE2)); + + var stream1 = combinedStream._streams[0]; + var stream2 = combinedStream._streams[1]; + + stream1.on('end', function() { + assert.ok(stream2.dataSize > 0); + }); + + var tmpFile = common.dir.tmp + '/combined.txt'; + var dest = fs.createWriteStream(tmpFile); + combinedStream.pipe(dest); + + dest.on('end', function() { + var written = fs.readFileSync(tmpFile, 'utf8'); + assert.strictEqual(written, EXPECTED); + }); +})(); diff --git a/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/request/node_modules/form-data/package.json b/node_modules/request/node_modules/form-data/package.json new file mode 100644 index 0000000..1948a5e --- /dev/null +++ b/node_modules/request/node_modules/form-data/package.json @@ -0,0 +1,43 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "form-data", + "description": "A module to create readable `\"multipart/form-data\"` streams. Can be used to submit forms and file uploads to other web applications.", + "version": "0.0.3", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-form-data.git" + }, + "main": "./lib/form_data", + "engines": { + "node": "*" + }, + "dependencies": { + "combined-stream": "0.0.3", + "mime": "~1.2.2", + "async": "~0.1.9" + }, + "devDependencies": { + "fake": "0.2.1", + "far": "0.0.1", + "formidable": "1.0.2", + "request": "~2.9.203" + }, + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "form-data@0.0.3", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "dist": { + "shasum": "6eea17b45790b42d779a1d581d1b3600fe0c7c0d" + }, + "_from": "form-data" +} diff --git a/node_modules/request/node_modules/form-data/test/common.js b/node_modules/request/node_modules/form-data/test/common.js new file mode 100644 index 0000000..8a26482 --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/common.js @@ -0,0 +1,14 @@ +var common = module.exports; +var path = require('path'); + +var rootDir = path.join(__dirname, '..'); +common.dir = { + lib: rootDir + '/lib', + fixture: rootDir + '/test/fixture', + tmp: rootDir + '/test/tmp', +}; + +common.assert = require('assert'); +common.fake = require('fake'); + +common.port = 8432; diff --git a/node_modules/request/node_modules/form-data/test/fixture/bacon.txt b/node_modules/request/node_modules/form-data/test/fixture/bacon.txt new file mode 100644 index 0000000..9804bbd --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/fixture/bacon.txt @@ -0,0 +1 @@ +Bacon is delicious. diff --git a/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg b/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg new file mode 100644 index 0000000..7cea4dd Binary files /dev/null and b/node_modules/request/node_modules/form-data/test/fixture/unicycle.jpg differ diff --git a/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js b/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js new file mode 100644 index 0000000..44d3b4d --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js @@ -0,0 +1,93 @@ +var common = require('../common'); +var assert = common.assert; +var FormData = require(common.dir.lib + '/form_data'); +var fake = require('fake').create(); +var fs = require('fs'); + +(function testEmptyForm() { + var form = new FormData(); + var callback = fake.callback(arguments.callee.name + '-getLength'); + var calls = fake.expectAnytime(callback, [null, 0]).calls; + + form.getLength(callback); + + // Make sure our response is async + assert.strictEqual(calls.length, 0); +})(); + +(function testUtf8String() { + var FIELD = 'my_field'; + var VALUE = 'May the € be with you'; + + var form = new FormData(); + form.append(FIELD, VALUE); + var callback = fake.callback(arguments.callee.name + '-getLength'); + + var expectedLength = + form._overheadLength + + Buffer.byteLength(VALUE) + + form._lastBoundary().length; + + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + +(function testBuffer() { + var FIELD = 'my_field'; + var VALUE = new Buffer(23); + + var form = new FormData(); + form.append(FIELD, VALUE); + var callback = fake.callback(arguments.callee.name + '-getLength'); + + var expectedLength = + form._overheadLength + + VALUE.length + + form._lastBoundary().length; + + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + + +(function testStringFileBufferFile() { + var fields = [ + { + name: 'my_field', + value: 'Test 123', + }, + { + name: 'my_image', + value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), + }, + { + name: 'my_buffer', + value: new Buffer('123'), + }, + { + name: 'my_txt', + value: fs.createReadStream(common.dir.fixture + '/bacon.txt'), + }, + ]; + + var form = new FormData(); + var expectedLength = 0; + + fields.forEach(function(field) { + form.append(field.name, field.value); + if (field.value.path) { + var stat = fs.statSync(field.value.path); + expectedLength += stat.size; + } else { + expectedLength += field.value.length; + } + }); + + expectedLength += form._overheadLength + form._lastBoundary().length; + + var callback = fake.callback(arguments.callee.name + '-getLength'); + fake.expectAnytime(callback, [null, expectedLength]); + form.getLength(callback); +})(); + + diff --git a/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js b/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js new file mode 100644 index 0000000..6dc2fb2 --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = common.assert; + +var FormData = require(common.dir.lib + '/form_data'); + +(function testOneBoundaryPerForm() { + var form = new FormData(); + var boundary = form.getBoundary(); + + assert.equal(boundary, form.getBoundary()); + assert.equal(boundary.length, 50); +})(); + +(function testUniqueBoundaryPerForm() { + var formA = new FormData(); + var formB = new FormData(); + assert.notEqual(formA.getBoundary(), formB.getBoundary()); +})(); diff --git a/node_modules/request/node_modules/form-data/test/integration/test-http-response.js b/node_modules/request/node_modules/form-data/test/integration/test-http-response.js new file mode 100644 index 0000000..8e183fe --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/integration/test-http-response.js @@ -0,0 +1,121 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS; +var server; + +var parsedUrl = parseUrl(remoteFile) + , options = { + method: 'get', + port: parsedUrl.port || 80, + path: parsedUrl.pathname, + host: parsedUrl.hostname + } + ; + +http.request(options, function(res) { + + FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'remote_file', value: res } + ]; + + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + server.listen(common.port, function() { + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + + }); + + +}).end(); + +server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(remoteFile)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/request/node_modules/form-data/test/integration/test-pipe.js b/node_modules/request/node_modules/form-data/test/integration/test-pipe.js new file mode 100644 index 0000000..acc39df --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/integration/test-pipe.js @@ -0,0 +1,111 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(common.port, function() { + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + var request = http.request({ + method: 'post', + port: common.port, + path: '/upload', + headers: form.getHeaders() + }); + + form.pipe(request); + + request.on('response', function(res) { + server.close(); + }); +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/request/node_modules/form-data/test/integration/test-submit.js b/node_modules/request/node_modules/form-data/test/integration/test-submit.js new file mode 100644 index 0000000..c40e88f --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/integration/test-submit.js @@ -0,0 +1,107 @@ +var common = require('../common'); +var assert = common.assert; +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('request'); +var fs = require('fs'); +var FormData = require(common.dir.lib + '/form_data'); +var IncomingForm = require('formidable').IncomingForm; + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg') }, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // formidable is broken so let's do it manual way + // + // var form = new IncomingForm(); + // form.uploadDir = common.dir.tmp; + // form.parse(req); + // form + // .on('field', function(name, value) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(value, field.value+''); + // }) + // .on('file', function(name, file) { + // var field = FIELDS.shift(); + // assert.strictEqual(name, field.name); + // assert.strictEqual(file.name, path.basename(field.value.path)); + // // mime.lookup file.NAME == 'my_file' ? + // assert.strictEqual(file.type, mime.lookup(file.name)); + // }) + // .on('end', function() { + // res.writeHead(200); + // res.end('done'); + // }); + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + req.on('data', function(d) { + data += d; + }); + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + +}); + +server.listen(common.port, function() { + var form = new FormData(); + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + + form.submit('http://localhost:' + common.port + '/', function(err, res) { + + if (err) { + throw err; + } + + assert.strictEqual(res.statusCode, 200); + server.close(); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/request/node_modules/form-data/test/run.js b/node_modules/request/node_modules/form-data/test/run.js new file mode 100755 index 0000000..0bb8e82 --- /dev/null +++ b/node_modules/request/node_modules/form-data/test/run.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var far = require('far').create(); + +far.add(__dirname); +far.include(/test-.*\.js$/); + +far.execute(); diff --git a/node_modules/request/node_modules/mime/LICENSE b/node_modules/request/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/request/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +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. diff --git a/node_modules/request/node_modules/mime/README.md b/node_modules/request/node_modules/mime/README.md new file mode 100644 index 0000000..b90552a --- /dev/null +++ b/node_modules/request/node_modules/mime/README.md @@ -0,0 +1,63 @@ +# mime + +Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community. + +## Install + +Install with [npm](http://github.com/isaacs/npm): + + npm install mime + +## API - Queries + +### mime.lookup(path) +Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.'). E.g. + + var mime = require('mime'); + + mime.lookup('/path/to/file.txt'); // => 'text/plain' + mime.lookup('file.txt'); // => 'text/plain' + mime.lookup('.TXT'); // => 'text/plain' + mime.lookup('htm'); // => 'text/html' + +### mime.extension(type) +Get the default extension for `type` + + mime.extension('text/html'); // => 'html' + mime.extension('application/octet-stream'); // => 'bin' + +### mime.charsets.lookup() + +Map mime-type to charset + + mime.charsets.lookup('text/plain'); // => 'UTF-8' + +(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.) + +## API - Defining Custom Types + +The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types). + +### mime.define() + +Add custom mime/extension mappings + + mime.define({ + 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'], + 'application/x-my-type': ['x-mt', 'x-mtt'], + // etc ... + }); + + mime.lookup('x-sft'); // => 'text/x-some-format' + +The first entry in the extensions array is returned by `mime.extension()`. E.g. + + mime.extension('text/x-some-format'); // => 'x-sf' + +### mime.load(filepath) + +Load mappings from an Apache ".types" format file + + mime.load('./my_project.types'); + +The .types file format is simple - See the `types` dir for examples. diff --git a/node_modules/request/node_modules/mime/mime.js b/node_modules/request/node_modules/mime/mime.js new file mode 100644 index 0000000..1e00585 --- /dev/null +++ b/node_modules/request/node_modules/mime/mime.js @@ -0,0 +1,104 @@ +var path = require('path'); +var fs = require('fs'); + +function Mime() { + // Map of extension -> mime type + this.types = Object.create(null); + + // Map of mime type -> extension + this.extensions = Object.create(null); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * @param map (Object) type definitions + */ +Mime.prototype.define = function (map) { + for (var type in map) { + var exts = map[type]; + + for (var i = 0; i < exts.length; i++) { + this.types[exts[i]] = type; + } + + // Default extension is the first one we encounter + if (!this.extensions[type]) { + this.extensions[type] = exts[0]; + } + } +}; + +/** + * Load an Apache2-style ".types" file + * + * This may be called multiple times (it's expected). Where files declare + * overlapping types/extensions, the last file wins. + * + * @param file (String) path of file to load. + */ +Mime.prototype.load = function(file) { + // Read file and split into lines + var map = {}, + content = fs.readFileSync(file, 'ascii'), + lines = content.split(/[\r\n]+/); + + lines.forEach(function(line) { + // Clean up whitespace/comments, and split into fields + var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/); + map[fields.shift()] = fields; + }); + + this.define(map); +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.lookup = function(path, fallback) { + var ext = path.replace(/.*[\.\/]/, '').toLowerCase(); + + return this.types[ext] || fallback || this.default_type; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.extension = function(mimeType) { + return this.extensions[mimeType]; +}; + +// Default instance +var mime = new Mime(); + +// Load local copy of +// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types +mime.load(path.join(__dirname, 'types/mime.types')); + +// Load additional types from node.js community +mime.load(path.join(__dirname, 'types/node.types')); + +// Default type +mime.default_type = mime.lookup('bin'); + +// +// Additional API specific to the default instance +// + +mime.Mime = Mime; + +/** + * Lookup a charset based on mime type. + */ +mime.charsets = { + lookup: function(mimeType, fallback) { + // Assume text types are utf8 + return (/^text\//).test(mimeType) ? 'UTF-8' : fallback; + } +} + +module.exports = mime; diff --git a/node_modules/request/node_modules/mime/package.json b/node_modules/request/node_modules/mime/package.json new file mode 100644 index 0000000..06e2ee5 --- /dev/null +++ b/node_modules/request/node_modules/mime/package.json @@ -0,0 +1,42 @@ +{ + "author": { + "name": "Robert Kieffer", + "email": "robert@broofa.com", + "url": "http://github.com/broofa" + }, + "contributors": [ + { + "name": "Benjamin Thomas", + "email": "benjamin@benjaminthomas.org", + "url": "http://github.com/bentomas" + } + ], + "dependencies": {}, + "description": "A comprehensive library for mime-type mapping", + "devDependencies": {}, + "keywords": [ + "util", + "mime" + ], + "main": "mime.js", + "name": "mime", + "repository": { + "url": "git://github.com/broofa/node-mime.git", + "type": "git" + }, + "version": "1.2.7", + "_npmUser": { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + "_id": "mime@1.2.7", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.24", + "_nodeVersion": "v0.8.1", + "_defaultsLoaded": true, + "_from": "mime" +} diff --git a/node_modules/request/node_modules/mime/test.js b/node_modules/request/node_modules/mime/test.js new file mode 100644 index 0000000..cbad034 --- /dev/null +++ b/node_modules/request/node_modules/mime/test.js @@ -0,0 +1,55 @@ +/** + * Usage: node test.js + */ + +var mime = require('./mime'); +var assert = require('assert'); + +function eq(a, b) { + console.log('Test: ' + a + ' === ' + b); + assert.strictEqual.apply(null, arguments); +} + +console.log(Object.keys(mime.extensions).length + ' types'); +console.log(Object.keys(mime.types).length + ' extensions\n'); + +// +// Test mime lookups +// + +eq('text/plain', mime.lookup('text.txt')); +eq('text/plain', mime.lookup('.text.txt')); +eq('text/plain', mime.lookup('.txt')); +eq('text/plain', mime.lookup('txt')); +eq('application/octet-stream', mime.lookup('text.nope')); +eq('fallback', mime.lookup('text.fallback', 'fallback')); +eq('application/octet-stream', mime.lookup('constructor')); +eq('text/plain', mime.lookup('TEXT.TXT')); +eq('text/event-stream', mime.lookup('text/event-stream')); +eq('application/x-web-app-manifest+json', mime.lookup('text.webapp')); + +// +// Test extensions +// + +eq('txt', mime.extension(mime.types.text)); +eq('html', mime.extension(mime.types.htm)); +eq('bin', mime.extension('application/octet-stream')); +eq(undefined, mime.extension('constructor')); + +// +// Test node types +// + +eq('application/octet-stream', mime.lookup('file.buffer')); +eq('audio/mp4', mime.lookup('file.m4a')); + +// +// Test charsets +// + +eq('UTF-8', mime.charsets.lookup('text/plain')); +eq(undefined, mime.charsets.lookup(mime.types.js)); +eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback')); + +console.log('\nOK'); diff --git a/node_modules/request/node_modules/mime/types/mime.types b/node_modules/request/node_modules/mime/types/mime.types new file mode 100644 index 0000000..b90b165 --- /dev/null +++ b/node_modules/request/node_modules/mime/types/mime.types @@ -0,0 +1,1588 @@ +# This file maps Internet media types to unique file extension(s). +# Although created for httpd, this file is used by many software systems +# and has been placed in the public domain for unlimited redisribution. +# +# The table below contains both registered and (common) unregistered types. +# A type that has no unique extension can be ignored -- they are listed +# here to guide configurations toward known types and to make it easier to +# identify "new" types. File extensions are also commonly used to indicate +# content languages and encodings, so choose them carefully. +# +# Internet media types should be registered as described in RFC 4288. +# The registry is at . +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/calendar+xml +# application/cals-1840 +# application/ccmp+xml +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +application/docbook+xml dbk +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +application/gml+xml gml +application/gpx+xml gpx +application/gxf gxf +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +application/inkml+xml ink inkml +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +application/jsonml+json jsonml +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink+xml metalink +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/omdoc+xml omdoc +application/onenote onetoc onetoc2 onetmp onepkg +application/oxps oxps +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rpki-ghostbusters gbr +application/rpki-manifest mft +application/rpki-roa roa +# application/rpki-updown +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssdl+xml ssdl +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vcard+xml +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.formscentral.fcdt fcdt +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.astraea-software.iota iota +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.collection+json +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +# application/vnd.curl +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.dart dart +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.dece.zip uvz uvvz +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.ds-keypoint kpxx +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +# application/vnd.eprints.data+xml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +# application/vnd.hal+json +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +# application/vnd.hzn-3d-crossword +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +# application/vnd.innopath.wamp.notification +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.newsmessage+xml +# application/vnd.iptc.g2.packageitem+xml +# application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +# application/vnd.ms-color.iccprofile +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +# application/vnd.ms-opentype +# application/vnd.ms-package.obfuscated-opentype +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +# application/vnd.ms-printing.printticket+xml +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +application/vnd.mynfc taglet +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.nitf ntf nitf +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oftn.l10n+json +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-feature-handler+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.cab-user-prefs+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.pal+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +application/vnd.osgi.subsystem esa +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.rn-realmedia-vbr rmvb +application/vnd.route66.link66+xml link66 +# application/vnd.rs-274x +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.package smzip +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.through-ngn +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +# application/x-amf +application/x-apple-diskimage dmg +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-blorb blb blorb +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cbr cbr cba cbt cbz cb7 +application/x-cdlink vcd +application/x-cfs-compressed cfs +application/x-chat chat +application/x-chess-pgn pgn +application/x-conference nsc +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-dgc-compressed dgc +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-envoy evy +application/x-eva eva +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-freearc arc +application/x-futuresplash spl +application/x-gca-compressed gca +application/x-glulx ulx +application/x-gnumeric gnumeric +application/x-gramps-xml gramps +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-install-instructions install +application/x-iso9660-image iso +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-lzh-compressed lzh lha +application/x-mie mie +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-shortcut lnk +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf wmz emf emz +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-nzb nzb +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-research-info-systems ris +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-sql sql +application/x-stuffit sit +application/x-stuffitx sitx +application/x-subrip srt +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-t3vm-image t3 +application/x-tads gam +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-tgif obj +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xliff+xml xlf +application/x-xpinstall xpi +application/x-xz xz +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 +# application/x400-bp +application/xaml+xml xaml +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xproc+xml xpl +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dv +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/fwdred +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/ip-mr_v2.5 +# audio/isac +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +# audio/musepack +audio/ogg oga ogg spx +# audio/opus +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +audio/s3m s3m +audio/silk sil +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.dvb.file +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-caf caf +audio/x-flac flac +audio/x-matroska mka +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +# audio/x-tta +audio/x-wav wav +audio/xm xm +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/sgi sgi +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.ms-photo wdp +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-3ds 3ds +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-mrsid-image sid +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-tga tga +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +model/x3d+binary x3db x3dbz +model/x3d+vrml x3dv x3dvz +model/x3d+xml x3d x3dz +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/cache-manifest appcache +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +# text/fwdred +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +text/vcard vcard +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +text/vnd.dvb.subtitle sub +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-java-source java +text/x-opml opml +text/x-pascal p pas +text/x-nfo nfo +text/x-setext etx +text/x-sfv sfv +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.dvb.file dvb +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-matroska mkv mk3d mks +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-vob vob +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +video/x-smv smv +x-conference/x-cooltalk ice diff --git a/node_modules/request/node_modules/mime/types/node.types b/node_modules/request/node_modules/mime/types/node.types new file mode 100644 index 0000000..9097334 --- /dev/null +++ b/node_modules/request/node_modules/mime/types/node.types @@ -0,0 +1,59 @@ +# What: Google Chrome Extension +# Why: To allow apps to (work) be served with the right content type header. +# http://codereview.chromium.org/2830017 +# Added by: niftylettuce +application/x-chrome-extension crx + +# What: OTF Message Silencer +# Why: To silence the "Resource interpreted as font but transferred with MIME +# type font/otf" message that occurs in Google Chrome +# Added by: niftylettuce +font/opentype otf + +# What: HTC support +# Why: To properly render .htc files such as CSS3PIE +# Added by: niftylettuce +text/x-component htc + +# What: HTML5 application cache manifest +# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps +# per https://developer.mozilla.org/en/offline_resources_in_firefox +# Added by: louisremi +text/cache-manifest appcache manifest + +# What: node binary buffer format +# Why: semi-standard extension w/in the node community +# Added by: tootallnate +application/octet-stream buffer + +# What: The "protected" MP-4 formats used by iTunes. +# Why: Required for streaming music to browsers (?) +# Added by: broofa +application/mp4 m4p +audio/mp4 m4a + +# What: Music playlist format (http://en.wikipedia.org/wiki/M3U) +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +application/x-mpegURL m3u8 + +# What: Video format, Part of RFC1890 +# Why: See https://github.com/bentomas/node-mime/pull/6 +# Added by: mjrusso +video/MP2T ts + +# What: The FLAC lossless codec format +# Why: Streaming and serving FLAC audio +# Added by: jacobrask +audio/flac flac + +# What: EventSource mime type +# Why: mime type of Server-Sent Events stream +# http://www.w3.org/TR/eventsource/#text-event-stream +# Added by: francois2metz +text/event-stream event-stream + +# What: Mozilla App manifest mime type +# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests +# Added by: ednapiranha +application/x-web-app-manifest+json webapp diff --git a/node_modules/request/oauth.js b/node_modules/request/oauth.js new file mode 100644 index 0000000..e35bfa6 --- /dev/null +++ b/node_modules/request/oauth.js @@ -0,0 +1,43 @@ +var crypto = require('crypto') + , qs = require('querystring') + ; + +function sha1 (key, body) { + return crypto.createHmac('sha1', key).update(body).digest('base64') +} + +function rfc3986 (str) { + return encodeURIComponent(str) + .replace(/!/g,'%21') + .replace(/\*/g,'%2A') + .replace(/\(/g,'%28') + .replace(/\)/g,'%29') + .replace(/'/g,'%27') + ; +} + +function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) { + // adapted from https://dev.twitter.com/docs/auth/oauth and + // https://dev.twitter.com/docs/auth/creating-signature + + var querystring = Object.keys(params).sort().map(function(key){ + // big WTF here with the escape + encoding but it's what twitter wants + return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key])) + }).join('%26') + + var base = [ + httpMethod ? httpMethod.toUpperCase() : 'GET', + rfc3986(base_uri), + querystring + ].join('&') + + var key = [ + consumer_secret, + token_secret || '' + ].map(rfc3986).join('&') + + return sha1(key, base) +} + +exports.hmacsign = hmacsign +exports.rfc3986 = rfc3986 diff --git a/node_modules/request/package.json b/node_modules/request/package.json new file mode 100644 index 0000000..bc2b653 --- /dev/null +++ b/node_modules/request/package.json @@ -0,0 +1,40 @@ +{ + "name": "request", + "description": "Simplified HTTP request client.", + "tags": [ + "http", + "simple", + "util", + "utility" + ], + "version": "2.12.0", + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com" + }, + "repository": { + "type": "git", + "url": "http://github.com/mikeal/request.git" + }, + "bugs": { + "url": "http://github.com/mikeal/request/issues" + }, + "engines": [ + "node >= 0.3.6" + ], + "main": "./main", + "dependencies": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + }, + "bundleDependencies": [ + "form-data", + "mime" + ], + "scripts": { + "test": "node tests/run.js" + }, + "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n
    \n  npm install request\n
    \n\nOr from source:\n\n
    \n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n
    \n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n if (!error && response.statusCode == 200) {\n console.log(body) // Print the google web page.\n }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n if (req.method === 'PUT') {\n req.pipe(request.put('http://mysite.com/doodle.png'))\n } else if (req.method === 'GET' || req.method === 'HEAD') {\n request.get('http://mysite.com/doodle.png').pipe(resp)\n } \n }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n var x = request('http://mysite.com/doodle.png')\n req.pipe(x)\n x.pipe(resp)\n }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n if (req.url === '/doodle.png') {\n r.get('http://google.com/doodle.png').pipe(resp)\n }\n})\n```\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nUrl encoded forms are simple\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload')\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))\nform.append('remote_file', request('http://google.com/doodle.png'))\n```\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n , oauth =\n { callback: 'http://mysite.com/callback/'\n , consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n }\n , url = 'https://api.twitter.com/oauth/request_token'\n ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n // Assume by some stretch of magic you aquired the verifier\n var access_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: access_token.oauth_token\n , verifier: VERIFIER\n , token_secret: access_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/oauth/access_token'\n ;\n request.post({url:url, oauth:oauth}, function (e, r, body) {\n var perm_token = qs.parse(body)\n , oauth = \n { consumer_key: CONSUMER_KEY\n , consumer_secret: CONSUMER_SECRET\n , token: perm_token.oauth_token\n , token_secret: perm_token.oauth_token_secret\n }\n , url = 'https://api.twitter.com/1/users/show.json?'\n , params = \n { screen_name: perm_token.screen_name\n , user_id: perm_token.user_id\n }\n ;\n url += qs.stringify(params)\n request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n console.log(user)\n })\n })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for POST and PUT requests. Must be buffer or string.\n* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options) \n \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n var request = require('request')\n , rand = Math.floor(Math.random()*100000000).toString()\n ;\n request(\n { method: 'PUT'\n , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n , multipart: \n [ { 'content-type': 'application/json'\n , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n }\n , { body: 'I am an attachment' }\n ] \n }\n , function (error, response, body) {\n if(response.statusCode == 201){\n console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n } else {\n console.log('error: '+ response.statusCode)\n console.log(body)\n }\n }\n )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n request('http://images.google.com')\n})\n```\n", + "_id": "request@2.12.0", + "_from": "request" +} diff --git a/node_modules/request/tests/googledoodle.png b/node_modules/request/tests/googledoodle.png new file mode 100644 index 0000000..f80c9c5 Binary files /dev/null and b/node_modules/request/tests/googledoodle.png differ diff --git a/node_modules/request/tests/run.js b/node_modules/request/tests/run.js new file mode 100644 index 0000000..538a65c --- /dev/null +++ b/node_modules/request/tests/run.js @@ -0,0 +1,45 @@ +var spawn = require('child_process').spawn + , exitCode = 0 + ; + +var tests = [ + 'test-body.js' + , 'test-cookie.js' + , 'test-cookiejar.js' + , 'test-defaults.js' + , 'test-errors.js' + , 'test-form.js' + , 'test-follow-all-303.js' + , 'test-follow-all.js' + , 'test-headers.js' + , 'test-httpModule.js' + , 'test-https.js' + , 'test-https-strict.js' + , 'test-oauth.js' + , 'test-params.js' + , 'test-pipes.js' + , 'test-pool.js' + , 'test-protocol-changing-redirect.js' + , 'test-proxy.js' + , 'test-piped-redirect.js' + , 'test-qs.js' + , 'test-redirect.js' + , 'test-timeout.js' + , 'test-toJSON.js' + , 'test-tunnel.js' +] + +var next = function () { + if (tests.length === 0) process.exit(exitCode); + + var file = tests.shift() + console.log(file) + var proc = spawn('node', [ 'tests/' + file ]) + proc.stdout.pipe(process.stdout) + proc.stderr.pipe(process.stderr) + proc.on('exit', function (code) { + exitCode += code || 0 + next() + }) +} +next() diff --git a/node_modules/request/tests/server.js b/node_modules/request/tests/server.js new file mode 100644 index 0000000..b6eacba --- /dev/null +++ b/node_modules/request/tests/server.js @@ -0,0 +1,90 @@ +var fs = require('fs') + , http = require('http') + , path = require('path') + , https = require('https') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + ; + +exports.createServer = function (port) { + port = port || 6767 + var s = http.createServer(function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'http://localhost:'+port + return s; +} + +exports.createSSLServer = function(port, opts) { + port = port || 16767 + + var options = { 'key' : path.join(__dirname, 'ssl', 'test.key') + , 'cert': path.join(__dirname, 'ssl', 'test.crt') + } + if (opts) { + for (var i in opts) options[i] = opts[i] + } + + for (var i in options) { + options[i] = fs.readFileSync(options[i]) + } + + var s = https.createServer(options, function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'https://localhost:'+port + return s; +} + +exports.createPostStream = function (text) { + var postStream = new stream.Stream(); + postStream.writeable = true; + postStream.readable = true; + setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0); + return postStream; +} +exports.createPostValidator = function (text, reqContentType) { + var l = function (req, resp) { + var r = ''; + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) { + var boundary = req.headers['content-type'].split('boundary=')[1]; + text = text.replace(/__BOUNDARY__/g, boundary); + } + if (r !== text) console.log(r, text); + assert.equal(r, text) + if (reqContentType) { + assert.ok(req.headers['content-type']) + assert.ok(~req.headers['content-type'].indexOf(reqContentType)) + } + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write('OK') + resp.end() + }) + } + return l; +} +exports.createGetResponse = function (text, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + resp.write(text) + resp.end() + } + return l; +} +exports.createChunkResponse = function (chunks, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + chunks.forEach(function (chunk) { + resp.write(chunk) + }) + resp.end() + } + return l; +} diff --git a/node_modules/request/tests/squid.conf b/node_modules/request/tests/squid.conf new file mode 100644 index 0000000..0d4a3b6 --- /dev/null +++ b/node_modules/request/tests/squid.conf @@ -0,0 +1,77 @@ +# +# Recommended minimum configuration: +# +acl manager proto cache_object +acl localhost src 127.0.0.1/32 ::1 +acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1 + +# Example rule allowing access from your local networks. +# Adapt to list your (internal) IP networks from where browsing +# should be allowed +acl localnet src 10.0.0.0/8 # RFC1918 possible internal network +acl localnet src 172.16.0.0/12 # RFC1918 possible internal network +acl localnet src 192.168.0.0/16 # RFC1918 possible internal network +acl localnet src fc00::/7 # RFC 4193 local private network range +acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT + +# +# Recommended minimum Access Permission configuration: +# +# Only allow cachemgr access from localhost +http_access allow manager localhost +http_access deny manager + +# Deny requests to certain unsafe ports +http_access deny !Safe_ports + +# Deny CONNECT to other than secure SSL ports +#http_access deny CONNECT !SSL_ports + +# We strongly recommend the following be uncommented to protect innocent +# web applications running on the proxy server who think the only +# one who can access services on "localhost" is a local user +#http_access deny to_localhost + +# +# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS +# + +# Example rule allowing access from your local networks. +# Adapt localnet in the ACL section to list your (internal) IP networks +# from where browsing should be allowed +http_access allow localnet +http_access allow localhost + +# And finally deny all other access to this proxy +http_access deny all + +# Squid normally listens to port 3128 +http_port 3128 + +# We recommend you to use at least the following line. +hierarchy_stoplist cgi-bin ? + +# Uncomment and adjust the following to add a disk cache directory. +#cache_dir ufs /usr/local/var/cache 100 16 256 + +# Leave coredumps in the first cache dir +coredump_dir /usr/local/var/cache + +# Add any of your own refresh_pattern entries above these. +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern . 0 20% 4320 diff --git a/node_modules/request/tests/ssl/ca/ca.cnf b/node_modules/request/tests/ssl/ca/ca.cnf new file mode 100644 index 0000000..425a889 --- /dev/null +++ b/node_modules/request/tests/ssl/ca/ca.cnf @@ -0,0 +1,20 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no +output_password = password + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = request Certificate Authority +CN = requestCA +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/request/tests/ssl/ca/ca.crl b/node_modules/request/tests/ssl/ca/ca.crl new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/request/tests/ssl/ca/ca.crt b/node_modules/request/tests/ssl/ca/ca.crt new file mode 100644 index 0000000..b4524e4 --- /dev/null +++ b/node_modules/request/tests/ssl/ca/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvTCCAiYCCQDn+P/MSbDsWjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGiMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxJjAkBgNVBAsTHXJlcXVlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MRIwEAYDVQQDEwlyZXF1ZXN0Q0ExJjAkBgkqhkiG9w0BCQEWF21pa2VhbEBtaWtl +YWxyb2dlcnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t9pQUAK4 +5XJYTI6NrF0n3G2HZsfN+rPYSVzzL8SuVyb1tHXos+vbPm3NKI4E8X1yVAXU8CjJ +5SqXnp4DAypAhaseho81cbhk7LXUhFz78OvAa+OD+xTAEAnNQ8tGUr4VGyplEjfD +xsBVuqV2j8GPNTftr+drOCFlqfAgMrBn4wIDAQABMA0GCSqGSIb3DQEBBQUAA4GB +ADVdTlVAL45R+PACNS7Gs4o81CwSclukBu4FJbxrkd4xGQmurgfRrYYKjtqiopQm +D7ysRamS3HMN9/VKq2T7r3z1PMHPAy7zM4uoXbbaTKwlnX4j/8pGPn8Ca3qHXYlo +88L/OOPc6Di7i7qckS3HFbXQCTiULtxWmy97oEuTwrAj +-----END CERTIFICATE----- diff --git a/node_modules/request/tests/ssl/ca/ca.csr b/node_modules/request/tests/ssl/ca/ca.csr new file mode 100644 index 0000000..e48c56e --- /dev/null +++ b/node_modules/request/tests/ssl/ca/ca.csr @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICBjCCAW8CAQAwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEmMCQGA1UECxMdcmVxdWVzdCBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAMTCXJlcXVlc3RDQTEmMCQGCSqG +SIb3DQEJARYXbWlrZWFsQG1pa2VhbHJvZ2Vycy5jb20wgZ8wDQYJKoZIhvcNAQEB +BQADgY0AMIGJAoGBALu32lBQArjlclhMjo2sXSfcbYdmx836s9hJXPMvxK5XJvW0 +deiz69s+bc0ojgTxfXJUBdTwKMnlKpeengMDKkCFqx6GjzVxuGTstdSEXPvw68Br +44P7FMAQCc1Dy0ZSvhUbKmUSN8PGwFW6pXaPwY81N+2v52s4IWWp8CAysGfjAgMB +AAGgIzAhBgkqhkiG9w0BCQcxFBMScGFzc3dvcmQgY2hhbGxlbmdlMA0GCSqGSIb3 +DQEBBQUAA4GBAGJO7grHeVHXetjHEK8urIxdnvfB2qeZeObz4GPKIkqUurjr0rfj +bA3EK1kDMR5aeQWR8RunixdM16Q6Ry0lEdLVWkdSwRN9dmirIHT9cypqnD/FYOia +SdezZ0lUzXgmJIwRYRwB1KSMMocIf52ll/xC2bEGg7/ZAEuAyAgcZV3X +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/request/tests/ssl/ca/ca.key b/node_modules/request/tests/ssl/ca/ca.key new file mode 100644 index 0000000..a53e7f7 --- /dev/null +++ b/node_modules/request/tests/ssl/ca/ca.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C8B5887048377F02 + +nyD5ZH0Wup2uWsDvurq5mKDaDrf8lvNn9w0SH/ZkVnfR1/bkwqrFriqJWvZNUG+q +nS0iBYczsWLJnbub9a1zLOTENWUKVD5uqbC3aGHhnoUTNSa27DONgP8gHOn6JgR+ +GAKo01HCSTiVT4LjkwN337QKHnMP2fTzg+IoC/CigvMcq09hRLwU1/guq0GJKGwH +gTxYNuYmQC4Tjh8vdS4liF+Ve/P3qPR2CehZrIOkDT8PHJBGQJRo4xGUIB7Tpk38 +VCk+UZ0JCS2coY8VkY/9tqFJp/ZnnQQVmaNbdRqg7ECKL+bXnNo7yjzmazPZmPe3 +/ShbE0+CTt7LrjCaQAxWbeDzqfo1lQfgN1LulTm8MCXpQaJpv7v1VhIhQ7afjMYb +4thW/ypHPiYS2YJCAkAVlua9Oxzzh1qJoh8Df19iHtpd79Q77X/qf+1JvITlMu0U +gi7yEatmQcmYNws1mtTC1q2DXrO90c+NZ0LK/Alse6NRL/xiUdjug2iHeTf/idOR +Gg/5dSZbnnlj1E5zjSMDkzg6EHAFmHV4jYGSAFLEQgp4V3ZhMVoWZrvvSHgKV/Qh +FqrAK4INr1G2+/QTd09AIRzfy3/j6yD4A9iNaOsEf9Ua7Qh6RcALRCAZTWR5QtEf +dX+iSNJ4E85qXs0PqwkMDkoaxIJ+tmIRJY7y8oeylV8cfGAi8Soubt/i3SlR8IHC +uDMas/2OnwafK3N7ODeE1i7r7wkzQkSHaEz0TrF8XRnP25jAICCSLiMdAAjKfxVb +EvzsFSuAy3Jt6bU3hSLY9o4YVYKE+68ITMv9yNjvTsEiW+T+IbN34w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/request/tests/ssl/ca/ca.srl b/node_modules/request/tests/ssl/ca/ca.srl new file mode 100644 index 0000000..17128db --- /dev/null +++ b/node_modules/request/tests/ssl/ca/ca.srl @@ -0,0 +1 @@ +ADF62016AA40C9C3 diff --git a/node_modules/request/tests/ssl/ca/server.cnf b/node_modules/request/tests/ssl/ca/server.cnf new file mode 100644 index 0000000..cd1fd1e --- /dev/null +++ b/node_modules/request/tests/ssl/ca/server.cnf @@ -0,0 +1,19 @@ +[ req ] +default_bits = 1024 +days = 3650 +distinguished_name = req_distinguished_name +attributes = req_attributes +prompt = no + +[ req_distinguished_name ] +C = US +ST = CA +L = Oakland +O = request +OU = testing +CN = testing.request.mikealrogers.com +emailAddress = mikeal@mikealrogers.com + +[ req_attributes ] +challengePassword = password challenge + diff --git a/node_modules/request/tests/ssl/ca/server.crt b/node_modules/request/tests/ssl/ca/server.crt new file mode 100644 index 0000000..efe96ce --- /dev/null +++ b/node_modules/request/tests/ssl/ca/server.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICejCCAeMCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1 +ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG +A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n +ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGjMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT +B3JlcXVlc3QxEDAOBgNVBAsTB3Rlc3RpbmcxKTAnBgNVBAMTIHRlc3RpbmcucmVx +dWVzdC5taWtlYWxyb2dlcnMuY29tMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlr +ZWFscm9nZXJzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDgVl0jMumvOpmM +20W5v9yhGgZj8hPhEQF/N7yCBVBn/rWGYm70IHC8T/pR5c0LkWc5gdnCJEvKWQjh +DBKxZD8FAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEABShRkNgFbgs4vUWW9R9deNJj +7HJoiTmvkmoOC7QzcYkjdgHbOxsSq3rBnwxsVjY9PAtPwBn0GRspOeG7KzKRgySB +kb22LyrCFKbEOfKO/+CJc80ioK9zEPVjGsFMyAB+ftYRqM+s/4cQlTg/m89l01wC +yapjN3RxZbInGhWR+jA= +-----END CERTIFICATE----- diff --git a/node_modules/request/tests/ssl/ca/server.csr b/node_modules/request/tests/ssl/ca/server.csr new file mode 100644 index 0000000..a8e7595 --- /dev/null +++ b/node_modules/request/tests/ssl/ca/server.csr @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBgjCCASwCAQAwgaMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE +BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEQMA4GA1UECxMHdGVzdGluZzEp +MCcGA1UEAxMgdGVzdGluZy5yZXF1ZXN0Lm1pa2VhbHJvZ2Vycy5jb20xJjAkBgkq +hkiG9w0BCQEWF21pa2VhbEBtaWtlYWxyb2dlcnMuY29tMFwwDQYJKoZIhvcNAQEB +BQADSwAwSAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAaAjMCEGCSqGSIb3DQEJBzEU +ExJwYXNzd29yZCBjaGFsbGVuZ2UwDQYJKoZIhvcNAQEFBQADQQBD3E5WekQzCEJw +7yOcqvtPYIxGaX8gRKkYfLPoj3pm3GF5SGqtJKhylKfi89szHXgktnQgzff9FN+A +HidVJ/3u +-----END CERTIFICATE REQUEST----- diff --git a/node_modules/request/tests/ssl/ca/server.js b/node_modules/request/tests/ssl/ca/server.js new file mode 100644 index 0000000..05e21c1 --- /dev/null +++ b/node_modules/request/tests/ssl/ca/server.js @@ -0,0 +1,28 @@ +var fs = require("fs") +var https = require("https") +var options = { key: fs.readFileSync("./server.key") + , cert: fs.readFileSync("./server.crt") } + +var server = https.createServer(options, function (req, res) { + res.writeHead(200) + res.end() + server.close() +}) +server.listen(1337) + +var ca = fs.readFileSync("./ca.crt") +var agent = new https.Agent({ host: "localhost", port: 1337, ca: ca }) + +https.request({ host: "localhost" + , method: "HEAD" + , port: 1337 + , headers: { host: "testing.request.mikealrogers.com" } + , agent: agent + , ca: [ ca ] + , path: "/" }, function (res) { + if (res.client.authorized) { + console.log("node test: OK") + } else { + throw new Error(res.client.authorizationError) + } +}).end() diff --git a/node_modules/request/tests/ssl/ca/server.key b/node_modules/request/tests/ssl/ca/server.key new file mode 100644 index 0000000..72d8698 --- /dev/null +++ b/node_modules/request/tests/ssl/ca/server.key @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg +cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAQJAK+r8ZM2sze8s7FRo/ApB +iRBtO9fCaIdJwbwJnXKo4RKwZDt1l2mm+fzZ+/QaQNjY1oTROkIIXmnwRvZWfYlW +gQIhAPKYsG+YSBN9o8Sdp1DMyZ/rUifKX3OE6q9tINkgajDVAiEA7Ltqh01+cnt0 +JEnud/8HHcuehUBLMofeg0G+gCnSbXECIQCqDvkXsWNNLnS/3lgsnvH0Baz4sbeJ +rjIpuVEeg8eM5QIgbu0+9JmOV6ybdmmiMV4yAncoF35R/iKGVHDZCAsQzDECIQDZ +0jGz22tlo5YMcYSqrdD3U4sds1pwiAaWFRbCunoUJw== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/request/tests/ssl/npm-ca.crt b/node_modules/request/tests/ssl/npm-ca.crt new file mode 100644 index 0000000..fde2fe9 --- /dev/null +++ b/node_modules/request/tests/ssl/npm-ca.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x +IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w +bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y +MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV +BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj +YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA +aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE +OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz +Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl +y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC +l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv +yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl +ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op +-----END CERTIFICATE----- diff --git a/node_modules/request/tests/ssl/test.crt b/node_modules/request/tests/ssl/test.crt new file mode 100644 index 0000000..b357f86 --- /dev/null +++ b/node_modules/request/tests/ssl/test.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQzCCAawCCQCO/XWtRFck1jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJU +SDEQMA4GA1UECBMHQmFuZ2tvazEOMAwGA1UEBxMFU2lsb20xGzAZBgNVBAoTElRo +ZSBSZXF1ZXN0IE1vZHVsZTEYMBYGA1UEAxMPcmVxdWVzdC5leGFtcGxlMB4XDTEx +MTIwMzAyMjkyM1oXDTIxMTEzMDAyMjkyM1owZjELMAkGA1UEBhMCVEgxEDAOBgNV +BAgTB0Jhbmdrb2sxDjAMBgNVBAcTBVNpbG9tMRswGQYDVQQKExJUaGUgUmVxdWVz +dCBNb2R1bGUxGDAWBgNVBAMTD3JlcXVlc3QuZXhhbXBsZTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwmctddZqlA48+NXs0yOy92DijcQV1jf87zMiYAIlNUto +wghVbTWgJU5r0pdKrD16AptnWJTzKanhItEX8XCCPgsNkq1afgTtJP7rNkwu3xcj +eIMkhJg/ay4ZnkbnhYdsii5VTU5prix6AqWRAhbkBgoA+iVyHyof8wvZyKBoFTMC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQB6BybMJbpeiABgihDfEVBcAjDoQ8gUMgwV +l4NulugfKTDmArqnR9aPd4ET5jX5dkMP4bwCHYsvrcYDeWEQy7x5WWuylOdKhua4 +L4cEi2uDCjqEErIG3cc1MCOk6Cl6Ld6tkIzQSf953qfdEACRytOeUqLNQcrXrqeE +c7U8F6MWLQ== +-----END CERTIFICATE----- diff --git a/node_modules/request/tests/ssl/test.key b/node_modules/request/tests/ssl/test.key new file mode 100644 index 0000000..b85810d --- /dev/null +++ b/node_modules/request/tests/ssl/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDCZy111mqUDjz41ezTI7L3YOKNxBXWN/zvMyJgAiU1S2jCCFVt +NaAlTmvSl0qsPXoCm2dYlPMpqeEi0RfxcII+Cw2SrVp+BO0k/us2TC7fFyN4gySE +mD9rLhmeRueFh2yKLlVNTmmuLHoCpZECFuQGCgD6JXIfKh/zC9nIoGgVMwIDAQAB +AoGBALXFwfUf8vHTSmGlrdZS2AGFPvEtuvldyoxi9K5u8xmdFCvxnOcLsF2RsTHt +Mu5QYWhUpNJoG+IGLTPf7RJdj/kNtEs7xXqWy4jR36kt5z5MJzqiK+QIgiO9UFWZ +fjUb6oeDnTIJA9YFBdYi97MDuL89iU/UK3LkJN3hd4rciSbpAkEA+MCkowF5kSFb +rkOTBYBXZfiAG78itDXN6DXmqb9XYY+YBh3BiQM28oxCeQYyFy6pk/nstnd4TXk6 +V/ryA2g5NwJBAMgRKTY9KvxJWbESeMEFe2iBIV0c26/72Amgi7ZKUCLukLfD4tLF ++WSZdmTbbqI1079YtwaiOVfiLm45Q/3B0eUCQAaQ/0eWSGE+Yi8tdXoVszjr4GXb +G81qBi91DMu6U1It+jNfIba+MPsiHLcZJMVb4/oWBNukN7bD1nhwFWdlnu0CQQCf +Is9WHkdvz2RxbZDxb8verz/7kXXJQJhx5+rZf7jIYFxqX3yvTNv3wf2jcctJaWlZ +fVZwB193YSivcgt778xlAkEAprYUz3jczjF5r2hrgbizPzPDR94tM5BTO3ki2v3w +kbf+j2g7FNAx6kZiVN8XwfLc8xEeUGiPKwtq3ddPDFh17w== +-----END RSA PRIVATE KEY----- diff --git a/node_modules/request/tests/test-body.js b/node_modules/request/tests/test-body.js new file mode 100644 index 0000000..a624397 --- /dev/null +++ b/node_modules/request/tests/test-body.js @@ -0,0 +1,117 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetEncoding : + { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex')) + , encoding: 'hex' + , expectBody: "efa3bfcea9e29883" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + , testPutMultipartPreambleCRLF : + { resp: server.createPostValidator( + '\r\n--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , preambleCRLF: true + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/request/tests/test-cookie.js b/node_modules/request/tests/test-cookie.js new file mode 100644 index 0000000..6c6a7a7 --- /dev/null +++ b/node_modules/request/tests/test-cookie.js @@ -0,0 +1,29 @@ +var Cookie = require('../vendor/cookie') + , assert = require('assert'); + +var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT'; +var cookie = new Cookie(str); + +// test .toString() +assert.equal(cookie.toString(), str); + +// test .path +assert.equal(cookie.path, '/'); + +// test .httpOnly +assert.equal(cookie.httpOnly, true); + +// test .name +assert.equal(cookie.name, 'Sid'); + +// test .value +assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="'); + +// test .expires +assert.equal(cookie.expires instanceof Date, true); + +// test .path default +var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' }); +assert.equal(cookie.path, '/bar'); + +console.log('All tests passed'); diff --git a/node_modules/request/tests/test-cookiejar.js b/node_modules/request/tests/test-cookiejar.js new file mode 100644 index 0000000..76fcd71 --- /dev/null +++ b/node_modules/request/tests/test-cookiejar.js @@ -0,0 +1,90 @@ +var Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , assert = require('assert'); + +function expires(ms) { + return new Date(Date.now() + ms).toUTCString(); +} + +// test .get() expiration +(function() { + var jar = new Jar; + var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000)); + jar.add(cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 0); + }, 1000); + }, 5); +})(); + +// test .get() path support +(function() { + var jar = new Jar; + var a = new Cookie('sid=1234; path=/'); + var b = new Cookie('sid=1111; path=/foo/bar'); + var c = new Cookie('sid=2222; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + + // should remove the duplicates + assert.equal(jar.cookies.length, 2); + + // same name, same path, latter prevails + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], c); + + // same name, diff path, path specifity prevails, latter prevails + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], a); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=3333; path=/foo/bar'); + var c = new Cookie('pid=3333; path=/foo/bar'); + var d = new Cookie('sid=2222; path=/foo/'); + var e = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + jar.add(d); + jar.add(e); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 2); + assert.equal(cookies[0], b); + assert.equal(cookies[1], c); + + var cookies = jar.get({ url: 'http://foo.com/foo/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], d); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], e); +})(); + +setTimeout(function() { + console.log('All tests passed'); +}, 1200); diff --git a/node_modules/request/tests/test-defaults.js b/node_modules/request/tests/test-defaults.js new file mode 100644 index 0000000..ba09418 --- /dev/null +++ b/node_modules/request/tests/test-defaults.js @@ -0,0 +1,114 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +s.listen(s.port, function () { + var counter = 0; + s.on('/get', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'GET') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end('TESTING!'); + }); + + // test get(string, function) + request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){ + if (e) throw e; + assert.deepEqual("TESTING!", b); + counter += 1; + }); + + s.on('/post', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], null); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/post-body', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers['content-type'], 'application/json'); + assert.equal(req.method, 'POST') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test post(string, object, function) with body + request.defaults({headers:{foo:"bar"}}).post(s.url + '/post-body', {json: true, body:{bar:"baz"}}, function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/del', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'DELETE') + resp.writeHead(200, {'Content-Type': 'application/json'}); + resp.end(JSON.stringify({foo:'bar'})); + }); + + // test .del(string, function) + request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){ + if (e) throw e; + assert.deepEqual('bar', b.foo); + counter += 1; + }); + + s.on('/head', function (req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.method, 'HEAD') + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test head.(object, function) + request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){ + if (e) throw e; + counter += 1; + }); + + s.on('/get_custom', function(req, resp) { + assert.equal(req.headers.foo, 'bar'); + assert.equal(req.headers.x, 'y'); + resp.writeHead(200, {'Content-Type': 'text/plain'}); + resp.end(); + }); + + // test custom request handler function + var defaultRequest = request.defaults({ + headers:{foo:"bar"} + , body: 'TESTING!' + }, function(uri, options, callback) { + var params = request.initParams(uri, options, callback); + options = params.options; + options.headers.x = 'y'; + + return request(params.uri, params.options, params.callback); + }); + + var msg = 'defaults test failed. head request should throw earlier'; + assert.throws(function() { + defaultRequest.head(s.url + '/get_custom', function(e, r, b) { + throw new Error(msg); + }); + counter+=1; + }, msg); + + defaultRequest.get(s.url + '/get_custom', function(e, r, b) { + if(e) throw e; + counter += 1; + console.log(counter.toString() + " tests passed."); + s.close(); + }); +}) diff --git a/node_modules/request/tests/test-errors.js b/node_modules/request/tests/test-errors.js new file mode 100644 index 0000000..1986a59 --- /dev/null +++ b/node_modules/request/tests/test-errors.js @@ -0,0 +1,37 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../main.js') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +try { + request(local, {multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/request/tests/test-follow-all-303.js b/node_modules/request/tests/test-follow-all-303.js new file mode 100644 index 0000000..3f2162d --- /dev/null +++ b/node_modules/request/tests/test-follow-all-303.js @@ -0,0 +1,30 @@ +var request = require('../main'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + console.error(req.method, req.url); + requests ++; + + if (req.method === 'POST') { + console.error('send 303'); + res.setHeader('location', req.url); + res.statusCode = 303; + res.end('try again, i guess\n'); + } else { + console.error('send 200') + res.end('ok: ' + requests); + } +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 2'); + assert.equal(requests, 2); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/request/tests/test-follow-all.js b/node_modules/request/tests/test-follow-all.js new file mode 100644 index 0000000..b78745b --- /dev/null +++ b/node_modules/request/tests/test-follow-all.js @@ -0,0 +1,35 @@ +var request = require('../main'); +var http = require('http'); +var requests = 0; +var assert = require('assert'); + +var server = http.createServer(function (req, res) { + requests ++; + + // redirect everything 3 times, no matter what. + var c = req.headers.cookie; + + if (!c) c = 0; + else c = +c.split('=')[1] || 0; + + if (c > 3) { + res.end('ok: '+requests); + return; + } + + res.setHeader('set-cookie', 'c=' + (c + 1)); + res.setHeader('location', req.url); + res.statusCode = 302; + res.end('try again, i guess\n'); +}); +server.listen(6767); + +request.post({ url: 'http://localhost:6767/foo', + followAllRedirects: true, + form: { foo: 'bar' } }, function (er, req, body) { + if (er) throw er; + assert.equal(body, 'ok: 5'); + assert.equal(requests, 5); + console.error('ok - ' + process.version); + server.close(); +}); diff --git a/node_modules/request/tests/test-form.js b/node_modules/request/tests/test-form.js new file mode 100644 index 0000000..aeefd31 --- /dev/null +++ b/node_modules/request/tests/test-form.js @@ -0,0 +1,79 @@ +var assert = require('assert') +var http = require('http'); +var path = require('path'); +var mime = require('mime'); +var request = require('../main.js'); +var fs = require('fs'); + +var remoteFile = 'http://nodejs.org/images/logo.png'; + +var FIELDS = [ + {name: 'my_field', value: 'my_value'}, + {name: 'my_buffer', value: new Buffer([1, 2, 3])}, + {name: 'my_file', value: fs.createReadStream(__dirname + '/unicycle.jpg')}, + {name: 'remote_file', value: request(remoteFile) } +]; + +var server = http.createServer(function(req, res) { + + // temp workaround + var data = ''; + req.setEncoding('utf8'); + + req.on('data', function(d) { + data += d; + }); + + req.on('end', function() { + // check for the fields' traces + + // 1st field : my_field + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 2nd field : my_buffer + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf(field.value) != -1 ); + + // 3rd field : my_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for unicycle.jpg traces + assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 ); + + // 4th field : remote_file + var field = FIELDS.shift(); + assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 ); + assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 ); + // check for http://nodejs.org/images/logo.png traces + assert.ok( data.indexOf('ImageReady') != -1 ); + assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 ); + + res.writeHead(200); + res.end('done'); + + }); + + +}); + +server.listen(8080, function() { + + var req = request.post('http://localhost:8080/upload', function () { + server.close(); + }) + var form = req.form() + + FIELDS.forEach(function(field) { + form.append(field.name, field.value); + }); + +}); + +process.on('exit', function() { + assert.strictEqual(FIELDS.length, 0); +}); diff --git a/node_modules/request/tests/test-headers.js b/node_modules/request/tests/test-headers.js new file mode 100644 index 0000000..31fe3f4 --- /dev/null +++ b/node_modules/request/tests/test-headers.js @@ -0,0 +1,52 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , s = server.createServer() + +s.listen(s.port, function () { + var serverUri = 'http://localhost:' + s.port + , numTests = 0 + , numOutstandingTests = 0 + + function createTest(requestObj, serverAssertFn) { + var testNumber = numTests; + numTests += 1; + numOutstandingTests += 1; + s.on('/' + testNumber, function (req, res) { + serverAssertFn(req, res); + res.writeHead(200); + res.end(); + }); + requestObj.url = serverUri + '/' + testNumber + request(requestObj, function (err, res, body) { + assert.ok(!err) + assert.equal(res.statusCode, 200) + numOutstandingTests -= 1 + if (numOutstandingTests === 0) { + console.log(numTests + ' tests passed.') + s.close() + } + }) + } + + // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified + createTest({headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar') + }) + + // Issue #125: headers.cookie + cookie jar + var jar = new Jar() + jar.add(new Cookie('quux=baz')); + createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) { + assert.ok(req.headers.cookie) + assert.equal(req.headers.cookie, 'foo=bar; quux=baz') + }) + + // There should be no cookie header when neither headers.cookie nor a cookie jar is specified + createTest({}, function (req, res) { + assert.ok(!req.headers.cookie) + }) +}) diff --git a/node_modules/request/tests/test-httpModule.js b/node_modules/request/tests/test-httpModule.js new file mode 100644 index 0000000..1866de2 --- /dev/null +++ b/node_modules/request/tests/test-httpModule.js @@ -0,0 +1,94 @@ +var http = require('http') + , https = require('https') + , server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var faux_requests_made = {'http':0, 'https':0} +function wrap_request(name, module) { + // Just like the http or https module, but note when a request is made. + var wrapped = {} + Object.keys(module).forEach(function(key) { + var value = module[key]; + + if(key != 'request') + wrapped[key] = value; + else + wrapped[key] = function(options, callback) { + faux_requests_made[name] += 1 + return value.apply(this, arguments) + } + }) + + return wrapped; +} + + +var faux_http = wrap_request('http', http) + , faux_https = wrap_request('https', https) + , plain_server = server.createServer() + , https_server = server.createSSLServer() + + +plain_server.listen(plain_server.port, function() { + plain_server.on('/plain', function (req, res) { + res.writeHead(200) + res.end('plain') + }) + plain_server.on('/to_https', function (req, res) { + res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'}) + res.end() + }) + + https_server.listen(https_server.port, function() { + https_server.on('/https', function (req, res) { + res.writeHead(200) + res.end('https') + }) + https_server.on('/to_plain', function (req, res) { + res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'}) + res.end() + }) + + run_tests() + run_tests({}) + run_tests({'http:':faux_http}) + run_tests({'https:':faux_https}) + run_tests({'http:':faux_http, 'https:':faux_https}) + }) +}) + +function run_tests(httpModules) { + var to_https = 'http://localhost:'+plain_server.port+'/to_https' + var to_plain = 'https://localhost:'+https_server.port+'/to_plain' + + request(to_https, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to SSL worked') + assert.equal(body, 'https', 'Received HTTPS server body') + done() + }) + + request(to_plain, {'httpModules':httpModules}, function (er, res, body) { + assert.ok(!er, 'Bounce to plaintext server worked') + assert.equal(body, 'plain', 'Received HTTPS server body') + done() + }) +} + + +var passed = 0; +function done() { + passed += 1 + var expected = 10 + + if(passed == expected) { + plain_server.close() + https_server.close() + + assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately') + assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately') + + console.log((expected+2) + ' tests passed.') + } +} diff --git a/node_modules/request/tests/test-https-strict.js b/node_modules/request/tests/test-https-strict.js new file mode 100644 index 0000000..470b68d --- /dev/null +++ b/node_modules/request/tests/test-https-strict.js @@ -0,0 +1,97 @@ +// a test where we validate the siguature of the keys +// otherwise exactly the same as the ssl test + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key') + , cert: path.resolve(__dirname, 'ssl/ca/server.crt') } + , s = server.createSSLServer(null, opts) + , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt') + , ca = fs.readFileSync(caFile) + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + test.strictSSL = true + test.ca = ca + test.headers = { host: 'testing.request.mikealrogers.com' } + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/request/tests/test-https.js b/node_modules/request/tests/test-https.js new file mode 100644 index 0000000..58e7db9 --- /dev/null +++ b/node_modules/request/tests/test-https.js @@ -0,0 +1,86 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + +var s = server.createSSLServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/request/tests/test-oauth.js b/node_modules/request/tests/test-oauth.js new file mode 100644 index 0000000..72ca923 --- /dev/null +++ b/node_modules/request/tests/test-oauth.js @@ -0,0 +1,117 @@ +var hmacsign = require('../oauth').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../main') + ; + +function getsignature (r) { + var sign + r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var rsign = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +setTimeout(function () { + console.log(getsignature(rsign)) + assert.equal(reqsign, getsignature(rsign)) +}) + +var raccsign = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +setTimeout(function () { + console.log(getsignature(raccsign)) + assert.equal(accsign, getsignature(raccsign)) +}, 1) + +var rupsign = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) +setTimeout(function () { + console.log(getsignature(rupsign)) + assert.equal(upsign, getsignature(rupsign)) +}, 1) + + + + diff --git a/node_modules/request/tests/test-params.js b/node_modules/request/tests/test-params.js new file mode 100644 index 0000000..5ddb311 --- /dev/null +++ b/node_modules/request/tests/test-params.js @@ -0,0 +1,92 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetBuffer : + { resp : server.createGetResponse(new Buffer("TESTING!")) + , encoding: null + , expectBody: new Buffer("TESTING!") + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--__BOUNDARY__\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__\r\n\r\n' + + 'Oh hi.' + + '\r\n--__BOUNDARY__--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + //test.uri = s.url + '/' + i + request(s.url + '/' + i, test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) diff --git a/node_modules/request/tests/test-piped-redirect.js b/node_modules/request/tests/test-piped-redirect.js new file mode 100644 index 0000000..25bf35d --- /dev/null +++ b/node_modules/request/tests/test-piped-redirect.js @@ -0,0 +1,52 @@ +var http = require('http') + , assert = require('assert') + , request = require('../main.js') + ; + +var portOne = 8968 + , portTwo = 8969 + ; + + +// server one +var s1 = http.createServer(function (req, resp) +{ + if (req.url == '/original') + { + resp.writeHeader(302, {'location': '/redirected'}) + resp.end() + } + else if (req.url == '/redirected') + { + resp.writeHeader(200, {'content-type': 'text/plain'}) + resp.write('OK') + resp.end() + } + +}).listen(portOne); + + +// server two +var s2 = http.createServer(function (req, resp) +{ + + var x = request('http://localhost:'+portOne+'/original') + req.pipe(x) + x.pipe(resp) + +}).listen(portTwo, function() +{ + + var r = request('http://localhost:'+portTwo+'/original', function (err, res, body) { + + assert.equal(body, 'OK') + + s1.close() + s2.close() + + }); + + // it hangs, so wait a second :) + r.timeout = 1000; + +}); diff --git a/node_modules/request/tests/test-pipes.js b/node_modules/request/tests/test-pipes.js new file mode 100644 index 0000000..7162981 --- /dev/null +++ b/node_modules/request/tests/test-pipes.js @@ -0,0 +1,216 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + // Test pipeing to a request object with a json body + s.once('/push-json', server.createPostValidator("{\"foo\":\"bar\"}", "application/json")); + + var mybodydata = new stream.Stream(); + mybodydata.readable = true + + counter++ + var r2 = request.put({url:'http://localhost:3453/push-json',json:true}, function () { + check(); + }) + mybodydata.pipe(r2) + + mybodydata.emit('data', JSON.stringify({foo:"bar"})); + mybodydata.emit('end'); + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'application/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/png'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.png')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.png')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.png')), fs.readFileSync(path.join(__dirname, 'test.png'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.png')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + + s.on('/forward1', function (req, resp) { + resp.writeHead(302, {location:'/forward2'}) + resp.end() + }) + s.on('/forward2', function (req, resp) { + resp.writeHead('200', {'content-type':'image/png'}) + resp.write('d') + resp.end() + }) + + counter++ + var validateForward = new ValidationStream('d') + validateForward.on('end', check) + request.get('http://localhost:3453/forward1').pipe(validateForward) + + // Test pipe options + s.once('/opts', server.createGetResponse('opts response')); + + var optsStream = new stream.Stream(); + optsStream.writable = true + + var optsData = ''; + optsStream.write = function (buf) { + optsData += buf; + if (optsData === 'opts response') { + setTimeout(check, 10); + } + } + + optsStream.end = function () { + assert.fail('end called') + }; + + counter++ + request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false }) +}) diff --git a/node_modules/request/tests/test-pool.js b/node_modules/request/tests/test-pool.js new file mode 100644 index 0000000..1e7d578 --- /dev/null +++ b/node_modules/request/tests/test-pool.js @@ -0,0 +1,16 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200; + resp.end('asdf'); +}).listen(8080, function () { + request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) { + var agent = resp.request.agent; + assert.strictEqual(typeof agent, 'boolean'); + assert.strictEqual(agent, false); + s.close(); + }); +}); \ No newline at end of file diff --git a/node_modules/request/tests/test-protocol-changing-redirect.js b/node_modules/request/tests/test-protocol-changing-redirect.js new file mode 100644 index 0000000..f74e196 --- /dev/null +++ b/node_modules/request/tests/test-protocol-changing-redirect.js @@ -0,0 +1,60 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + + +var s = server.createServer() +var ss = server.createSSLServer() +var sUrl = 'http://localhost:' + s.port +var ssUrl = 'https://localhost:' + ss.port + +s.listen(s.port, bouncy(s, ssUrl)) +ss.listen(ss.port, bouncy(ss, sUrl)) + +var hits = {} +var expect = {} +var pending = 0 +function bouncy (s, server) { return function () { + + var redirs = { a: 'b' + , b: 'c' + , c: 'd' + , d: 'e' + , e: 'f' + , f: 'g' + , g: 'h' + , h: 'end' } + + var perm = true + Object.keys(redirs).forEach(function (p) { + var t = redirs[p] + + // switch type each time + var type = perm ? 301 : 302 + perm = !perm + s.on('/' + p, function (req, res) { + res.writeHead(type, { location: server + '/' + t }) + res.end() + }) + }) + + s.on('/end', function (req, res) { + var h = req.headers['x-test-key'] + hits[h] = true + pending -- + if (pending === 0) done() + }) +}} + +for (var i = 0; i < 5; i ++) { + pending ++ + var val = 'test_' + i + expect[val] = true + request({ url: (i % 2 ? sUrl : ssUrl) + '/a' + , headers: { 'x-test-key': val } }) +} + +function done () { + assert.deepEqual(hits, expect) + process.exit(0) +} diff --git a/node_modules/request/tests/test-proxy.js b/node_modules/request/tests/test-proxy.js new file mode 100644 index 0000000..647157c --- /dev/null +++ b/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/request/tests/test-qs.js b/node_modules/request/tests/test-qs.js new file mode 100644 index 0000000..1aac22b --- /dev/null +++ b/node_modules/request/tests/test-qs.js @@ -0,0 +1,28 @@ +var request = request = require('../main.js') + , assert = require('assert') + ; + + +// Test adding a querystring +var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req1.path) +}, 1) + +// Test replacing a querystring value +var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?q=search', req2.path) +}, 1) + +// Test appending a querystring value to the ones present in the uri +var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }}) +setTimeout(function() { + assert.equal('/?x=y&q=search', req3.path) +}, 1) + +// Test leaving a querystring alone +var req4 = request.get({ uri: 'http://www.google.com?x=y'}) +setTimeout(function() { + assert.equal('/?x=y', req4.path) +}, 1) diff --git a/node_modules/request/tests/test-redirect.js b/node_modules/request/tests/test-redirect.js new file mode 100644 index 0000000..b84844a --- /dev/null +++ b/node_modules/request/tests/test-redirect.js @@ -0,0 +1,154 @@ +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + +var s = server.createServer() + +s.listen(s.port, function () { + var server = 'http://localhost:' + s.port; + var hits = {} + var passed = 0; + + bouncer(301, 'temp') + bouncer(302, 'perm') + bouncer(302, 'nope') + + function bouncer(code, label) { + var landing = label+'_landing'; + + s.on('/'+label, function (req, res) { + hits[label] = true; + res.writeHead(code, { + 'location':server + '/'+landing, + 'set-cookie': 'ham=eggs' + }) + res.end() + }) + + s.on('/'+landing, function (req, res) { + if (req.method !== 'GET') { // We should only accept GET redirects + console.error("Got a non-GET request to the redirect destination URL"); + res.writeHead(400); + res.end(); + return; + } + // Make sure the cookie doesn't get included twice, see #139: + // Make sure cookies are set properly after redirect + assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs'); + hits[landing] = true; + res.writeHead(200) + res.end(landing) + }) + } + + // Permanent bounce + var jar = new Jar() + jar.add(new Cookie('quux=baz')) + request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.perm, 'Original request is to /perm') + assert.ok(hits.perm_landing, 'Forward to permanent landing URL') + assert.equal(body, 'perm_landing', 'Got permanent landing content') + passed += 1 + done() + }) + + // Temporary bounce + request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + // Prevent bouncing. + request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode) + assert.ok(hits.nope, 'Original request to /nope') + assert.ok(!hits.nope_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 302, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow post redirects by default + request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when post') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow post redirects when followAllRedirects true + request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects by default + request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode < 301) throw new Error('Status is not a redirect.') + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should not follow delete redirects even if followRedirect is set to true + request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(!hits.temp_landing, 'No chasing the redirect when delete') + assert.equal(res.statusCode, 301, 'Response is the bounce itself') + passed += 1 + done() + }) + + // Should follow delete redirects when followAllRedirects true + request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) { + if (er) throw er + if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode) + assert.ok(hits.temp, 'Original request is to /temp') + assert.ok(hits.temp_landing, 'Forward to temporary landing URL') + assert.equal(body, 'temp_landing', 'Got temporary landing content') + passed += 1 + done() + }) + + var reqs_done = 0; + function done() { + reqs_done += 1; + if(reqs_done == 9) { + console.log(passed + ' tests passed.') + s.close() + } + } +}) diff --git a/node_modules/request/tests/test-s3.js b/node_modules/request/tests/test-s3.js new file mode 100644 index 0000000..5f59c4a --- /dev/null +++ b/node_modules/request/tests/test-s3.js @@ -0,0 +1,13 @@ +var request = require('../main') + +var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', + { aws: + { key: 'AKIAI6KIQRRVMGK3WK5Q' + , secret: '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' + , bucket: 'log.curlybracecast.com' + } + }, function (e, resp, body) { + console.log(r.headers) + console.log(body) + } +) \ No newline at end of file diff --git a/node_modules/request/tests/test-timeout.js b/node_modules/request/tests/test-timeout.js new file mode 100644 index 0000000..673f8ad --- /dev/null +++ b/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/request/tests/test-toJSON.js b/node_modules/request/tests/test-toJSON.js new file mode 100644 index 0000000..b7c67ef --- /dev/null +++ b/node_modules/request/tests/test-toJSON.js @@ -0,0 +1,14 @@ +var request = require('../main') + , http = require('http') + , assert = require('assert') + ; + +var s = http.createServer(function (req, resp) { + resp.statusCode = 200 + resp.end('asdf') +}).listen(8080, function () { + var r = request('http://localhost:8080', function (e, resp) { + assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200) + s.close() + }) +}) \ No newline at end of file diff --git a/node_modules/request/tests/test-tunnel.js b/node_modules/request/tests/test-tunnel.js new file mode 100644 index 0000000..51e2126 --- /dev/null +++ b/node_modules/request/tests/test-tunnel.js @@ -0,0 +1,63 @@ +// test that we can tunnel a https request over an http proxy +// keeping all the CA and whatnot intact. +// +// Note: this requires that squid is installed. +// If the proxy fails to start, we'll just log a warning and assume success. + +var server = require('./server') + , assert = require('assert') + , request = require('../main.js') + , fs = require('fs') + , path = require('path') + , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt') + , ca = fs.readFileSync(caFile) + , child_process = require('child_process') + , sqConf = path.resolve(__dirname, 'squid.conf') + , sqArgs = ['-f', sqConf, '-N', '-d', '5'] + , proxy = 'http://localhost:3128' + , hadError = null + +var squid = child_process.spawn('squid', sqArgs); +var ready = false + +squid.stderr.on('data', function (c) { + console.error('SQUIDERR ' + c.toString().trim().split('\n') + .join('\nSQUIDERR ')) + ready = c.toString().match(/ready to serve requests/i) +}) + +squid.stdout.on('data', function (c) { + console.error('SQUIDOUT ' + c.toString().trim().split('\n') + .join('\nSQUIDOUT ')) +}) + +squid.on('exit', function (c) { + console.error('squid: exit '+c) + if (c && !ready) { + console.error('squid must be installed to run this test.') + console.error('skipping this test. please install squid and run again if you need to test tunneling.') + c = null + hadError = null + process.exit(0) + return + } + + if (c) { + hadError = hadError || new Error('Squid exited with '+c) + } + if (hadError) throw hadError +}) + +setTimeout(function F () { + if (!ready) return setTimeout(F, 100) + request({ uri: 'https://registry.npmjs.org/' + , proxy: 'http://localhost:3128' + , strictSSL: true + , ca: ca + , json: true }, function (er, body) { + hadError = er + console.log(er || typeof body) + if (!er) console.log("ok") + squid.kill('SIGKILL') + }) +}, 100) diff --git a/node_modules/request/tests/unicycle.jpg b/node_modules/request/tests/unicycle.jpg new file mode 100644 index 0000000..7cea4dd Binary files /dev/null and b/node_modules/request/tests/unicycle.jpg differ diff --git a/node_modules/request/tunnel.js b/node_modules/request/tunnel.js new file mode 100644 index 0000000..3f7bbb9 --- /dev/null +++ b/node_modules/request/tunnel.js @@ -0,0 +1,227 @@ +'use strict' + +var net = require('net') + , tls = require('tls') + , http = require('http') + , https = require('https') + , events = require('events') + , assert = require('assert') + , util = require('util') + ; + +exports.httpOverHttp = httpOverHttp +exports.httpsOverHttp = httpsOverHttp +exports.httpOverHttps = httpOverHttps +exports.httpsOverHttps = httpsOverHttps + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + return agent +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options) + agent.request = http.request + agent.createSocket = createSecureSocket + return agent +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + return agent +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options) + agent.request = https.request + agent.createSocket = createSecureSocket + return agent +} + + +function TunnelingAgent(options) { + var self = this + self.options = options || {} + self.proxyOptions = self.options.proxy || {} + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets + self.requests = [] + self.sockets = [] + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i] + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1) + pending.request.onSocket(socket) + return + } + } + socket.destroy() + self.removeSocket(socket) + }) +} +util.inherits(TunnelingAgent, events.EventEmitter) + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}) + return + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree) + socket.on('close', onCloseOrRemove) + socket.on('agentRemove', onCloseOrRemove) + req.onSocket(socket) + + function onFree() { + self.emit('free', socket, host, port) + } + + function onCloseOrRemove(err) { + self.removeSocket() + socket.removeListener('free', onFree) + socket.removeListener('close', onCloseOrRemove) + socket.removeListener('agentRemove', onCloseOrRemove) + } + }) +} + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this + var placeholder = {} + self.sockets.push(placeholder) + + var connectOptions = mergeOptions({}, self.proxyOptions, + { method: 'CONNECT' + , path: options.host + ':' + options.port + , agent: false + } + ) + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {} + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64') + } + + debug('making CONNECT request') + var connectReq = self.request(connectOptions) + connectReq.useChunkedEncodingByDefault = false // for v0.6 + connectReq.once('response', onResponse) // for v0.6 + connectReq.once('upgrade', onUpgrade) // for v0.6 + connectReq.once('connect', onConnect) // for v0.7 or later + connectReq.once('error', onError) + connectReq.end() + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head) + }) + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners() + socket.removeAllListeners() + + if (res.statusCode === 200) { + assert.equal(head.length, 0) + debug('tunneling connection has established') + self.sockets[self.sockets.indexOf(placeholder)] = socket + cb(socket) + } else { + debug('tunneling socket could not be established, statusCode=%d', res.statusCode) + var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } + } + + function onError(cause) { + connectReq.removeAllListeners() + + debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack) + var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message) + error.code = 'ECONNRESET' + options.request.emit('error', error) + self.removeSocket(placeholder) + } +} + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) return + + this.sockets.splice(pos, 1) + + var pending = this.requests.shift() + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket) + }) + } +} + +function createSecureSocket(options, cb) { + var self = this + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, + { servername: options.host + , socket: socket + } + )) + cb(secureSocket) + }) +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i] + if (typeof overrides === 'object') { + var keys = Object.keys(overrides) + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j] + if (overrides[k] !== undefined) { + target[k] = overrides[k] + } + } + } + } + return target +} + + +var debug +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments) + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0] + } else { + args.unshift('TUNNEL:') + } + console.error.apply(console, args) + } +} else { + debug = function() {} +} +exports.debug = debug // for test diff --git a/node_modules/request/uuid.js b/node_modules/request/uuid.js new file mode 100644 index 0000000..fc0588b --- /dev/null +++ b/node_modules/request/uuid.js @@ -0,0 +1,19 @@ +module.exports = function () { + var s = [], itoh = '0123456789ABCDEF' + + // Make array of random hex digits. The UUID only has 32 digits in it, but we + // allocate an extra items to make room for the '-'s we'll be inserting. + for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10) + + // Conform to RFC-4122, section 4.4 + s[14] = 4; // Set 4 high bits of time_high field to version + s[19] = (s[19] & 0x3) | 0x8 // Specify 2 high bits of clock sequence + + // Convert to hex chars + for (var i = 0; i <36; i++) s[i] = itoh[s[i]] + + // Insert '-'s + s[8] = s[13] = s[18] = s[23] = '-' + + return s.join('') +} diff --git a/node_modules/request/vendor/cookie/index.js b/node_modules/request/vendor/cookie/index.js new file mode 100644 index 0000000..ff44b3e --- /dev/null +++ b/node_modules/request/vendor/cookie/index.js @@ -0,0 +1,65 @@ +/*! + * Tobi - Cookie + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var url = require('url'); + +/** + * Initialize a new `Cookie` with the given cookie `str` and `req`. + * + * @param {String} str + * @param {IncomingRequest} req + * @api private + */ + +var Cookie = exports = module.exports = function Cookie(str, req) { + this.str = str; + + // Map the key/val pairs + str.split(/ *; */).reduce(function(obj, pair){ + var p = pair.indexOf('='); + var key = p > 0 ? pair.substring(0, p).trim() : pair.trim(); + var lowerCasedKey = key.toLowerCase(); + var value = p > 0 ? pair.substring(p + 1).trim() : true; + + if (!obj.name) { + // First key is the name + obj.name = key; + obj.value = value; + } + else if (lowerCasedKey === 'httponly') { + obj.httpOnly = value; + } + else { + obj[lowerCasedKey] = value; + } + return obj; + }, this); + + // Expires + this.expires = this.expires + ? new Date(this.expires) + : Infinity; + + // Default or trim path + this.path = this.path + ? this.path.trim(): req + ? url.parse(req.url).pathname: '/'; +}; + +/** + * Return the original cookie string. + * + * @return {String} + * @api public + */ + +Cookie.prototype.toString = function(){ + return this.str; +}; diff --git a/node_modules/request/vendor/cookie/jar.js b/node_modules/request/vendor/cookie/jar.js new file mode 100644 index 0000000..34920e0 --- /dev/null +++ b/node_modules/request/vendor/cookie/jar.js @@ -0,0 +1,72 @@ +/*! +* Tobi - CookieJar +* Copyright(c) 2010 LearnBoost +* MIT Licensed +*/ + +/** +* Module dependencies. +*/ + +var url = require('url'); + +/** +* Initialize a new `CookieJar`. +* +* @api private +*/ + +var CookieJar = exports = module.exports = function CookieJar() { + this.cookies = []; +}; + +/** +* Add the given `cookie` to the jar. +* +* @param {Cookie} cookie +* @api private +*/ + +CookieJar.prototype.add = function(cookie){ + this.cookies = this.cookies.filter(function(c){ + // Avoid duplication (same path, same name) + return !(c.name == cookie.name && c.path == cookie.path); + }); + this.cookies.push(cookie); +}; + +/** +* Get cookies for the given `req`. +* +* @param {IncomingRequest} req +* @return {Array} +* @api private +*/ + +CookieJar.prototype.get = function(req){ + var path = url.parse(req.url).pathname + , now = new Date + , specificity = {}; + return this.cookies.filter(function(cookie){ + if (0 == path.indexOf(cookie.path) && now < cookie.expires + && cookie.path.length > (specificity[cookie.name] || 0)) + return specificity[cookie.name] = cookie.path.length; + }); +}; + +/** +* Return Cookie string for the given `req`. +* +* @param {IncomingRequest} req +* @return {String} +* @api private +*/ + +CookieJar.prototype.cookieString = function(req){ + var cookies = this.get(req); + if (cookies.length) { + return cookies.map(function(cookie){ + return cookie.name + '=' + cookie.value; + }).join('; '); + } +}; diff --git a/node_modules/underscore/.npmignore b/node_modules/underscore/.npmignore new file mode 100644 index 0000000..2ce2684 --- /dev/null +++ b/node_modules/underscore/.npmignore @@ -0,0 +1,3 @@ +test/ +Rakefile +docs/ \ No newline at end of file diff --git a/node_modules/underscore/CNAME b/node_modules/underscore/CNAME new file mode 100644 index 0000000..a007e65 --- /dev/null +++ b/node_modules/underscore/CNAME @@ -0,0 +1 @@ +underscorejs.org diff --git a/node_modules/underscore/CONTRIBUTING.md b/node_modules/underscore/CONTRIBUTING.md new file mode 100644 index 0000000..36a9934 --- /dev/null +++ b/node_modules/underscore/CONTRIBUTING.md @@ -0,0 +1,9 @@ +## How to contribute to Underscore.js + +* Before you open a ticket or send a pull request, [search](https://github.com/documentcloud/underscore/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. + +* Before sending a pull request for a feature, be sure to have [tests](http://underscorejs.org/test/test.html). + +* Use the same coding style as the rest of the [codebase](https://github.com/documentcloud/underscore/blob/master/underscore.js). + +* In your pull request, do not add documentation or re-build the minified `underscore-min.js` file. We'll do those things before cutting a new release. \ No newline at end of file diff --git a/node_modules/underscore/LICENSE b/node_modules/underscore/LICENSE new file mode 100644 index 0000000..61d28c0 --- /dev/null +++ b/node_modules/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud + +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. \ No newline at end of file diff --git a/node_modules/underscore/README.md b/node_modules/underscore/README.md new file mode 100644 index 0000000..b1f3e50 --- /dev/null +++ b/node_modules/underscore/README.md @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ + /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ + \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore.js is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://underscorejs.org + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/node_modules/underscore/favicon.ico b/node_modules/underscore/favicon.ico new file mode 100644 index 0000000..0304968 Binary files /dev/null and b/node_modules/underscore/favicon.ico differ diff --git a/node_modules/underscore/index.html b/node_modules/underscore/index.html new file mode 100644 index 0000000..e62aa92 --- /dev/null +++ b/node_modules/underscore/index.html @@ -0,0 +1,2407 @@ + + + + + + + + + Underscore.js + + + + +
    + +
    + +

    + +

    + +

    + Underscore is a + utility-belt library for JavaScript that provides a lot of the + functional programming support that you would expect in + Prototype.js + (or Ruby), + but without extending any of the built-in JavaScript objects. It's the + tie to go along with jQuery's tux, + and Backbone.js's suspenders. +

    + +

    + Underscore provides 80-odd functions that support both the usual + functional suspects: map, select, invoke — + as well as more specialized helpers: function binding, javascript + templating, deep equality testing, and so on. It delegates to built-in + functions, if present, so modern browsers will use the + native implementations of forEach, map, reduce, + filter, every, some and indexOf. +

    + +

    + A complete Test & Benchmark Suite + is included for your perusal. +

    + +

    + You may also read through the annotated source code. +

    + +

    + The project is + hosted on GitHub. + You can report bugs and discuss features on the + issues page, + on Freenode in the #documentcloud channel, + or send tweets to @documentcloud. +

    + +

    + Underscore is an open-source component of DocumentCloud. +

    + +

    Downloads (Right-click, and use "Save As")

    + + + + + + + + + + + + + + + + + +
    Development Version (1.4.3)40kb, Uncompressed with Plentiful Comments
    Production Version (1.4.3)4kb, Minified and Gzipped
    Edge VersionUnreleased, current master, use at your own risk
    + +
    + +

    Collection Functions (Arrays or Objects)

    + +

    + each_.each(list, iterator, [context]) + Alias: forEach +
    + Iterates over a list of elements, yielding each in turn to an iterator + function. The iterator is bound to the context object, if one is + passed. Each invocation of iterator is called with three arguments: + (element, index, list). If list is a JavaScript object, iterator's + arguments will be (value, key, list). Delegates to the native + forEach function if it exists. +

    +
    +_.each([1, 2, 3], alert);
    +=> alerts each number in turn...
    +_.each({one : 1, two : 2, three : 3}, alert);
    +=> alerts each number value in turn...
    + +

    + map_.map(list, iterator, [context]) + Alias: collect +
    + Produces a new array of values by mapping each value in list + through a transformation function (iterator). If the native map method + exists, it will be used instead. If list is a JavaScript object, + iterator's arguments will be (value, key, list). +

    +
    +_.map([1, 2, 3], function(num){ return num * 3; });
    +=> [3, 6, 9]
    +_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
    +=> [3, 6, 9]
    + +

    + reduce_.reduce(list, iterator, memo, [context]) + Aliases: inject, foldl +
    + Also known as inject and foldl, reduce boils down a + list of values into a single value. Memo is the initial state + of the reduction, and each successive step of it should be returned by + iterator. The iterator is passed four arguments: the memo, + then the value and index (or key) of the iteration, + and finally a reference to the entire list. +

    +
    +var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
    +=> 6
    +
    + +

    + reduceRight_.reduceRight(list, iterator, memo, [context]) + Alias: foldr +
    + The right-associative version of reduce. Delegates to the + JavaScript 1.8 version of reduceRight, if it exists. Foldr + is not as useful in JavaScript as it would be in a language with lazy + evaluation. +

    +
    +var list = [[0, 1], [2, 3], [4, 5]];
    +var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
    +=> [4, 5, 2, 3, 0, 1]
    +
    + +

    + find_.find(list, iterator, [context]) + Alias: detect +
    + Looks through each value in the list, returning the first one that + passes a truth test (iterator). The function returns as + soon as it finds an acceptable element, and doesn't traverse the + entire list. +

    +
    +var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    +=> 2
    +
    + +

    + filter_.filter(list, iterator, [context]) + Alias: select +
    + Looks through each value in the list, returning an array of all + the values that pass a truth test (iterator). Delegates to the + native filter method, if it exists. +

    +
    +var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    +=> [2, 4, 6]
    +
    + +

    + where_.where(list, properties) +
    + Looks through each value in the list, returning an array of all + the values that contain all of the key-value pairs listed in properties. +

    +
    +_.where(listOfPlays, {author: "Shakespeare", year: 1611});
    +=> [{title: "Cymbeline", author: "Shakespeare", year: 1611},
    +    {title: "The Tempest", author: "Shakespeare", year: 1611}]
    +
    + +

    + reject_.reject(list, iterator, [context]) +
    + Returns the values in list without the elements that the truth + test (iterator) passes. The opposite of filter. +

    +
    +var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
    +=> [1, 3, 5]
    +
    + +

    + every_.every(list, iterator, [context]) + Alias: all +
    + Returns true if all of the values in the list pass the iterator + truth test. Delegates to the native method every, if present. +

    +
    +_.every([true, 1, null, 'yes'], _.identity);
    +=> false
    +
    + +

    + some_.some(list, [iterator], [context]) + Alias: any +
    + Returns true if any of the values in the list pass the + iterator truth test. Short-circuits and stops traversing the list + if a true element is found. Delegates to the native method some, + if present. +

    +
    +_.some([null, 0, 'yes', false]);
    +=> true
    +
    + +

    + contains_.contains(list, value) + Alias: include +
    + Returns true if the value is present in the list. + Uses indexOf internally, if list is an Array. +

    +
    +_.contains([1, 2, 3], 3);
    +=> true
    +
    + +

    + invoke_.invoke(list, methodName, [*arguments]) +
    + Calls the method named by methodName on each value in the list. + Any extra arguments passed to invoke will be forwarded on to the + method invocation. +

    +
    +_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
    +=> [[1, 5, 7], [1, 2, 3]]
    +
    + +

    + pluck_.pluck(list, propertyName) +
    + A convenient version of what is perhaps the most common use-case for + map: extracting a list of property values. +

    +
    +var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
    +_.pluck(stooges, 'name');
    +=> ["moe", "larry", "curly"]
    +
    + +

    + max_.max(list, [iterator], [context]) +
    + Returns the maximum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

    +
    +var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
    +_.max(stooges, function(stooge){ return stooge.age; });
    +=> {name : 'curly', age : 60};
    +
    + +

    + min_.min(list, [iterator], [context]) +
    + Returns the minimum value in list. If iterator is passed, + it will be used on each value to generate the criterion by which the + value is ranked. +

    +
    +var numbers = [10, 5, 100, 2, 1000];
    +_.min(numbers);
    +=> 2
    +
    + +

    + sortBy_.sortBy(list, iterator, [context]) +
    + Returns a sorted copy of list, ranked in ascending order by the + results of running each value through iterator. Iterator may + also be the string name of the property to sort by (eg. length). +

    +
    +_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
    +=> [5, 4, 6, 3, 1, 2]
    +
    + +

    + groupBy_.groupBy(list, iterator) +
    + Splits a collection into sets, grouped by the result of running each + value through iterator. If iterator is a string instead of + a function, groups by the property named by iterator on each of + the values. +

    +
    +_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
    +=> {1: [1.3], 2: [2.1, 2.4]}
    +
    +_.groupBy(['one', 'two', 'three'], 'length');
    +=> {3: ["one", "two"], 5: ["three"]}
    +
    + +

    + countBy_.countBy(list, iterator) +
    + Sorts a list into groups and returns a count for the number of objects + in each group. + Similar to groupBy, but instead of returning a list of values, + returns a count for the number of values in that group. +

    +
    +_.countBy([1, 2, 3, 4, 5], function(num) {
    +  return num % 2 == 0 ? 'even' : 'odd';
    +});
    +=> {odd: 3, even: 2}
    +
    + +

    + shuffle_.shuffle(list) +
    + Returns a shuffled copy of the list, using a version of the + Fisher-Yates shuffle. +

    +
    +_.shuffle([1, 2, 3, 4, 5, 6]);
    +=> [4, 1, 6, 3, 5, 2]
    +
    + +

    + toArray_.toArray(list) +
    + Converts the list (anything that can be iterated over), into a + real Array. Useful for transmuting the arguments object. +

    +
    +(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
    +=> [2, 3, 4]
    +
    + +

    + size_.size(list) +
    + Return the number of values in the list. +

    +
    +_.size({one : 1, two : 2, three : 3});
    +=> 3
    +
    + +

    Array Functions

    + +

    + + Note: All array functions will also work on the arguments object. + However, Underscore functions are not designed to work on "sparse" arrays. + +

    + +

    + first_.first(array, [n]) + Alias: head, take +
    + Returns the first element of an array. Passing n will + return the first n elements of the array. +

    +
    +_.first([5, 4, 3, 2, 1]);
    +=> 5
    +
    + +

    + initial_.initial(array, [n]) +
    + Returns everything but the last entry of the array. Especially useful on + the arguments object. Pass n to exclude the last n elements + from the result. +

    +
    +_.initial([5, 4, 3, 2, 1]);
    +=> [5, 4, 3, 2]
    +
    + +

    + last_.last(array, [n]) +
    + Returns the last element of an array. Passing n will return + the last n elements of the array. +

    +
    +_.last([5, 4, 3, 2, 1]);
    +=> 1
    +
    + +

    + rest_.rest(array, [index]) + Alias: tail, drop +
    + Returns the rest of the elements in an array. Pass an index + to return the values of the array from that index onward. +

    +
    +_.rest([5, 4, 3, 2, 1]);
    +=> [4, 3, 2, 1]
    +
    + +

    + compact_.compact(array) +
    + Returns a copy of the array with all falsy values removed. + In JavaScript, false, null, 0, "", + undefined and NaN are all falsy. +

    +
    +_.compact([0, 1, false, 2, '', 3]);
    +=> [1, 2, 3]
    +
    + +

    + flatten_.flatten(array, [shallow]) +
    + Flattens a nested array (the nesting can be to any depth). If you + pass shallow, the array will only be flattened a single level. +

    +
    +_.flatten([1, [2], [3, [[4]]]]);
    +=> [1, 2, 3, 4];
    +
    +_.flatten([1, [2], [3, [[4]]]], true);
    +=> [1, 2, 3, [[4]]];
    +
    + +

    + without_.without(array, [*values]) +
    + Returns a copy of the array with all instances of the values + removed. +

    +
    +_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
    +=> [2, 3, 4]
    +
    + +

    + union_.union(*arrays) +
    + Computes the union of the passed-in arrays: the list of unique items, + in order, that are present in one or more of the arrays. +

    +
    +_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
    +=> [1, 2, 3, 101, 10]
    +
    + +

    + intersection_.intersection(*arrays) +
    + Computes the list of values that are the intersection of all the arrays. + Each value in the result is present in each of the arrays. +

    +
    +_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
    +=> [1, 2]
    +
    + +

    + difference_.difference(array, *others) +
    + Similar to without, but returns the values from array that + are not present in the other arrays. +

    +
    +_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
    +=> [1, 3, 4]
    +
    + +

    + uniq_.uniq(array, [isSorted], [iterator]) + Alias: unique +
    + Produces a duplicate-free version of the array, using === to test + object equality. If you know in advance that the array is sorted, + passing true for isSorted will run a much faster algorithm. + If you want to compute unique items based on a transformation, pass an + iterator function. +

    +
    +_.uniq([1, 2, 1, 3, 1, 4]);
    +=> [1, 2, 3, 4]
    +
    + +

    + zip_.zip(*arrays) +
    + Merges together the values of each of the arrays with the + values at the corresponding position. Useful when you have separate + data sources that are coordinated through matching array indexes. + If you're working with a matrix of nested arrays, zip.apply + can transpose the matrix in a similar fashion. +

    +
    +_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
    +=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
    +
    + +

    + object_.object(list, [values]) +
    + Converts arrays into objects. Pass either a single list of + [key, value] pairs, or a list of keys, and a list of values. +

    +
    +_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
    +=> {moe: 30, larry: 40, curly: 50}
    +
    +_.object([['moe', 30], ['larry', 40], ['curly', 50]]);
    +=> {moe: 30, larry: 40, curly: 50}
    +
    + +

    + indexOf_.indexOf(array, value, [isSorted]) +
    + Returns the index at which value can be found in the array, + or -1 if value is not present in the array. Uses the native + indexOf function unless it's missing. If you're working with a + large array, and you know that the array is already sorted, pass true + for isSorted to use a faster binary search ... or, pass a number as + the third argument in order to look for the first matching value in the + array after the given index. +

    +
    +_.indexOf([1, 2, 3], 2);
    +=> 1
    +
    + +

    + lastIndexOf_.lastIndexOf(array, value, [fromIndex]) +
    + Returns the index of the last occurrence of value in the array, + or -1 if value is not present. Uses the native lastIndexOf + function if possible. Pass fromIndex to start your search at a + given index. +

    +
    +_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
    +=> 4
    +
    + +

    + sortedIndex_.sortedIndex(list, value, [iterator]) +
    + Uses a binary search to determine the index at which the value + should be inserted into the list in order to maintain the list's + sorted order. If an iterator is passed, it will be used to compute + the sort ranking of each value, including the value you pass. +

    +
    +_.sortedIndex([10, 20, 30, 40, 50], 35);
    +=> 3
    +
    + +

    + range_.range([start], stop, [step]) +
    + A function to create flexibly-numbered lists of integers, handy for + each and map loops. start, if omitted, defaults + to 0; step defaults to 1. Returns a list of integers + from start to stop, incremented (or decremented) by step, + exclusive. +

    +
    +_.range(10);
    +=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    +_.range(1, 11);
    +=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    +_.range(0, 30, 5);
    +=> [0, 5, 10, 15, 20, 25]
    +_.range(0, -10, -1);
    +=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
    +_.range(0);
    +=> []
    +
    + +

    Function (uh, ahem) Functions

    + +

    + bind_.bind(function, object, [*arguments]) +
    + Bind a function to an object, meaning that whenever + the function is called, the value of this will be the object. + Optionally, bind arguments to the function to pre-fill them, + also known as partial application. +

    +
    +var func = function(greeting){ return greeting + ': ' + this.name };
    +func = _.bind(func, {name : 'moe'}, 'hi');
    +func();
    +=> 'hi: moe'
    +
    + +

    + bindAll_.bindAll(object, [*methodNames]) +
    + Binds a number of methods on the object, specified by + methodNames, to be run in the context of that object whenever they + are invoked. Very handy for binding functions that are going to be used + as event handlers, which would otherwise be invoked with a fairly useless + this. If no methodNames are provided, all of the object's + function properties will be bound to it. +

    +
    +var buttonView = {
    +  label   : 'underscore',
    +  onClick : function(){ alert('clicked: ' + this.label); },
    +  onHover : function(){ console.log('hovering: ' + this.label); }
    +};
    +_.bindAll(buttonView);
    +jQuery('#underscore_button').bind('click', buttonView.onClick);
    +=> When the button is clicked, this.label will have the correct value...
    +
    + +

    + memoize_.memoize(function, [hashFunction]) +
    + Memoizes a given function by caching the computed result. Useful + for speeding up slow-running computations. If passed an optional + hashFunction, it will be used to compute the hash key for storing + the result, based on the arguments to the original function. The default + hashFunction just uses the first argument to the memoized function + as the key. +

    +
    +var fibonacci = _.memoize(function(n) {
    +  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
    +});
    +
    + +

    + delay_.delay(function, wait, [*arguments]) +
    + Much like setTimeout, invokes function after wait + milliseconds. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

    +
    +var log = _.bind(console.log, console);
    +_.delay(log, 1000, 'logged later');
    +=> 'logged later' // Appears after one second.
    +
    + +

    + defer_.defer(function, [*arguments]) +
    + Defers invoking the function until the current call stack has cleared, + similar to using setTimeout with a delay of 0. Useful for performing + expensive computations or HTML rendering in chunks without blocking the UI thread + from updating. If you pass the optional arguments, they will be + forwarded on to the function when it is invoked. +

    +
    +_.defer(function(){ alert('deferred'); });
    +// Returns from the function before the alert runs.
    +
    + +

    + throttle_.throttle(function, wait) +
    + Creates and returns a new, throttled version of the passed function, + that, when invoked repeatedly, will only actually call the original function + at most once per every wait + milliseconds. Useful for rate-limiting events that occur faster than you + can keep up with. +

    +
    +var throttled = _.throttle(updatePosition, 100);
    +$(window).scroll(throttled);
    +
    + +

    + debounce_.debounce(function, wait, [immediate]) +
    + Creates and returns a new debounced version of the passed function that + will postpone its execution until after + wait milliseconds have elapsed since the last time it + was invoked. Useful for implementing behavior that should only happen + after the input has stopped arriving. For example: rendering a + preview of a Markdown comment, recalculating a layout after the window + has stopped being resized, and so on. +

    + +

    + Pass true for the immediate parameter to cause + debounce to trigger the function on the leading instead of the + trailing edge of the wait interval. Useful in circumstances like + preventing accidental double-clicks on a "submit" button from firing a + second time. +

    + +
    +var lazyLayout = _.debounce(calculateLayout, 300);
    +$(window).resize(lazyLayout);
    +
    + +

    + once_.once(function) +
    + Creates a version of the function that can only be called one time. + Repeated calls to the modified function will have no effect, returning + the value from the original call. Useful for initialization functions, + instead of having to set a boolean flag and then check it later. +

    +
    +var initialize = _.once(createApplication);
    +initialize();
    +initialize();
    +// Application is only created once.
    +
    + +

    + after_.after(count, function) +
    + Creates a version of the function that will only be run after first + being called count times. Useful for grouping asynchronous responses, + where you want to be sure that all the async calls have finished, before + proceeding. +

    +
    +var renderNotes = _.after(notes.length, render);
    +_.each(notes, function(note) {
    +  note.asyncSave({success: renderNotes});
    +});
    +// renderNotes is run once, after all notes have saved.
    +
    + +

    + wrap_.wrap(function, wrapper) +
    + Wraps the first function inside of the wrapper function, + passing it as the first argument. This allows the wrapper to + execute code before and after the function runs, adjust the arguments, + and execute it conditionally. +

    +
    +var hello = function(name) { return "hello: " + name; };
    +hello = _.wrap(hello, function(func) {
    +  return "before, " + func("moe") + ", after";
    +});
    +hello();
    +=> 'before, hello: moe, after'
    +
    + +

    + compose_.compose(*functions) +
    + Returns the composition of a list of functions, where each function + consumes the return value of the function that follows. In math terms, + composing the functions f(), g(), and h() produces + f(g(h())). +

    +
    +var greet    = function(name){ return "hi: " + name; };
    +var exclaim  = function(statement){ return statement + "!"; };
    +var welcome = _.compose(exclaim, greet);
    +welcome('moe');
    +=> 'hi: moe!'
    +
    + +

    Object Functions

    + +

    + keys_.keys(object) +
    + Retrieve all the names of the object's properties. +

    +
    +_.keys({one : 1, two : 2, three : 3});
    +=> ["one", "two", "three"]
    +
    + +

    + values_.values(object) +
    + Return all of the values of the object's properties. +

    +
    +_.values({one : 1, two : 2, three : 3});
    +=> [1, 2, 3]
    +
    + +

    + pairs_.pairs(object) +
    + Convert an object into a list of [key, value] pairs. +

    +
    +_.pairs({one: 1, two: 2, three: 3});
    +=> [["one", 1], ["two", 2], ["three", 3]]
    +
    + +

    + invert_.invert(object) +
    + Returns a copy of the object where the keys have become the values + and the values the keys. For this to work, all of your object's values + should be unique and string serializable. +

    +
    +_.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"});
    +=> {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};
    +
    + +

    + functions_.functions(object) + Alias: methods +
    + Returns a sorted list of the names of every method in an object — + that is to say, the name of every function property of the object. +

    +
    +_.functions(_);
    +=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
    +
    + +

    + extend_.extend(destination, *sources) +
    + Copy all of the properties in the source objects over to the + destination object, and return the destination object. + It's in-order, so the last source will override properties of the same + name in previous arguments. +

    +
    +_.extend({name : 'moe'}, {age : 50});
    +=> {name : 'moe', age : 50}
    +
    + +

    + pick_.pick(object, *keys) +
    + Return a copy of the object, filtered to only have values for + the whitelisted keys (or array of valid keys). +

    +
    +_.pick({name : 'moe', age: 50, userid : 'moe1'}, 'name', 'age');
    +=> {name : 'moe', age : 50}
    +
    + +

    + omit_.omit(object, *keys) +
    + Return a copy of the object, filtered to omit the blacklisted + keys (or array of keys). +

    +
    +_.omit({name : 'moe', age : 50, userid : 'moe1'}, 'userid');
    +=> {name : 'moe', age : 50}
    +
    + +

    + defaults_.defaults(object, *defaults) +
    + Fill in null and undefined properties in object with values from the + defaults objects, and return the object. As soon as the + property is filled, further defaults will have no effect. +

    +
    +var iceCream = {flavor : "chocolate"};
    +_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
    +=> {flavor : "chocolate", sprinkles : "lots"}
    +
    + +

    + clone_.clone(object) +
    + Create a shallow-copied clone of the object. Any nested objects + or arrays will be copied by reference, not duplicated. +

    +
    +_.clone({name : 'moe'});
    +=> {name : 'moe'};
    +
    + +

    + tap_.tap(object, interceptor) +
    + Invokes interceptor with the object, and then returns object. + The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain. +

    +
    +_.chain([1,2,3,200])
    +  .filter(function(num) { return num % 2 == 0; })
    +  .tap(alert)
    +  .map(function(num) { return num * num })
    +  .value();
    +=> // [2, 200] (alerted)
    +=> [4, 40000]
    +
    + +

    + has_.has(object, key) +
    + Does the object contain the given key? Identical to + object.hasOwnProperty(key), but uses a safe reference to the + hasOwnProperty function, in case it's been + overridden accidentally. +

    +
    +_.has({a: 1, b: 2, c: 3}, "b");
    +=> true
    +
    + +

    + isEqual_.isEqual(object, other) +
    + Performs an optimized deep comparison between the two objects, to determine + if they should be considered equal. +

    +
    +var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
    +var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
    +moe == clone;
    +=> false
    +_.isEqual(moe, clone);
    +=> true
    +
    + +

    + isEmpty_.isEmpty(object) +
    + Returns true if object contains no values. +

    +
    +_.isEmpty([1, 2, 3]);
    +=> false
    +_.isEmpty({});
    +=> true
    +
    + +

    + isElement_.isElement(object) +
    + Returns true if object is a DOM element. +

    +
    +_.isElement(jQuery('body')[0]);
    +=> true
    +
    + +

    + isArray_.isArray(object) +
    + Returns true if object is an Array. +

    +
    +(function(){ return _.isArray(arguments); })();
    +=> false
    +_.isArray([1,2,3]);
    +=> true
    +
    + +

    + isObject_.isObject(value) +
    + Returns true if value is an Object. Note that JavaScript + arrays and functions are objects, while (normal) strings and numbers are not. +

    +
    +_.isObject({});
    +=> true
    +_.isObject(1);
    +=> false
    +
    + +

    + isArguments_.isArguments(object) +
    + Returns true if object is an Arguments object. +

    +
    +(function(){ return _.isArguments(arguments); })(1, 2, 3);
    +=> true
    +_.isArguments([1,2,3]);
    +=> false
    +
    + +

    + isFunction_.isFunction(object) +
    + Returns true if object is a Function. +

    +
    +_.isFunction(alert);
    +=> true
    +
    + +

    + isString_.isString(object) +
    + Returns true if object is a String. +

    +
    +_.isString("moe");
    +=> true
    +
    + +

    + isNumber_.isNumber(object) +
    + Returns true if object is a Number (including NaN). +

    +
    +_.isNumber(8.4 * 5);
    +=> true
    +
    + +

    + isFinite_.isFinite(object) +
    + Returns true if object is a finite Number. +

    +
    +_.isFinite(-101);
    +=> true
    +
    +_.isFinite(-Infinity);
    +=> false
    +
    + +

    + isBoolean_.isBoolean(object) +
    + Returns true if object is either true or false. +

    +
    +_.isBoolean(null);
    +=> false
    +
    + +

    + isDate_.isDate(object) +
    + Returns true if object is a Date. +

    +
    +_.isDate(new Date());
    +=> true
    +
    + +

    + isRegExp_.isRegExp(object) +
    + Returns true if object is a RegExp. +

    +
    +_.isRegExp(/moe/);
    +=> true
    +
    + +

    + isNaN_.isNaN(object) +
    + Returns true if object is NaN.
    Note: this is not + the same as the native isNaN function, which will also return + true if the variable is undefined. +

    +
    +_.isNaN(NaN);
    +=> true
    +isNaN(undefined);
    +=> true
    +_.isNaN(undefined);
    +=> false
    +
    + +

    + isNull_.isNull(object) +
    + Returns true if the value of object is null. +

    +
    +_.isNull(null);
    +=> true
    +_.isNull(undefined);
    +=> false
    +
    + +

    + isUndefined_.isUndefined(value) +
    + Returns true if value is undefined. +

    +
    +_.isUndefined(window.missingVariable);
    +=> true
    +
    + +

    Utility Functions

    + +

    + noConflict_.noConflict() +
    + Give control of the "_" variable back to its previous owner. Returns + a reference to the Underscore object. +

    +
    +var underscore = _.noConflict();
    + +

    + identity_.identity(value) +
    + Returns the same value that is used as the argument. In math: + f(x) = x
    + This function looks useless, but is used throughout Underscore as + a default iterator. +

    +
    +var moe = {name : 'moe'};
    +moe === _.identity(moe);
    +=> true
    + +

    + times_.times(n, iterator, [context]) +
    + Invokes the given iterator function n times. Each invocation of + iterator is called with an index argument. +
    + Note: this example uses the chaining syntax. +

    +
    +_(3).times(function(n){ genie.grantWishNumber(n); });
    + +

    + random_.random(min, max) +
    + Returns a random integer between min and max, inclusive. + If you only pass one argument, it will return a number between 0 + and that number. +

    +
    +_.random(0, 100);
    +=> 42
    + +

    + mixin_.mixin(object) +
    + Allows you to extend Underscore with your own utility functions. Pass + a hash of {name: function} definitions to have your functions + added to the Underscore object, as well as the OOP wrapper. +

    +
    +_.mixin({
    +  capitalize : function(string) {
    +    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
    +  }
    +});
    +_("fabio").capitalize();
    +=> "Fabio"
    +
    + +

    + uniqueId_.uniqueId([prefix]) +
    + Generate a globally-unique id for client-side models or DOM elements + that need one. If prefix is passed, the id will be appended to it. + Without prefix, returns an integer. +

    +
    +_.uniqueId('contact_');
    +=> 'contact_104'
    + +

    + escape_.escape(string) +
    + Escapes a string for insertion into HTML, replacing + &, <, >, ", ', and / characters. +

    +
    +_.escape('Curly, Larry & Moe');
    +=> "Curly, Larry &amp; Moe"
    + +

    + unescape_.unescape(string) +
    + The opposite of escape, replaces + &amp;, &lt;, &gt;, + &quot;, &#x27;, and &#x2F; + with their unescaped counterparts. +

    +
    +_.escape('Curly, Larry &amp; Moe');
    +=> "Curly, Larry & Moe"
    + +

    + result_.result(object, property) +
    + If the value of the named property is a function then invoke it; otherwise, return it. +

    +
    +var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
    +_.result(object, 'cheese');
    +=> "crumpets"
    +_.result(object, 'stuff');
    +=> "nonsense"
    + +

    + template_.template(templateString, [data], [settings]) +
    + Compiles JavaScript templates into functions that can be evaluated + for rendering. Useful for rendering complicated bits of HTML from JSON + data sources. Template functions can both interpolate variables, using + <%= … %>, as well as execute arbitrary JavaScript code, with + <% … %>. If you wish to interpolate a value, and have + it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a + data object that has properties corresponding to the template's free + variables. If you're writing a one-off, you can pass the data + object as the second parameter to template in order to render + immediately instead of returning a template function. The settings argument + should be a hash containing any _.templateSettings that should be overridden. +

    + +
    +var compiled = _.template("hello: <%= name %>");
    +compiled({name : 'moe'});
    +=> "hello: moe"
    +
    +var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
    +_.template(list, {people : ['moe', 'curly', 'larry']});
    +=> "<li>moe</li><li>curly</li><li>larry</li>"
    +
    +var template = _.template("<b><%- value %></b>");
    +template({value : '<script>'});
    +=> "<b>&lt;script&gt;</b>"
    + +

    + You can also use print from within JavaScript code. This is + sometimes more convenient than using <%= ... %>. +

    + +
    +var compiled = _.template("<% print('Hello ' + epithet); %>");
    +compiled({epithet: "stooge"});
    +=> "Hello stooge."
    + +

    + If ERB-style delimiters aren't your cup of tea, you can change Underscore's + template settings to use different symbols to set off interpolated code. + Define an interpolate regex to match expressions that should be + interpolated verbatim, an escape regex to match expressions that should + be inserted after being HTML escaped, and an evaluate regex to match + expressions that should be evaluated without insertion into the resulting + string. You may define or omit any combination of the three. + For example, to perform + Mustache.js + style templating: +

    + +
    +_.templateSettings = {
    +  interpolate : /\{\{(.+?)\}\}/g
    +};
    +
    +var template = _.template("Hello {{ name }}!");
    +template({name : "Mustache"});
    +=> "Hello Mustache!"
    + +

    + By default, template places the values from your data in the local scope + via the with statement. However, you can specify a single variable name + with the variable setting. This can significantly improve the speed + at which a template is able to render. +

    + +
    +_.template("Using 'with': <%= data.answer %>", {answer: 'no'}, {variable: 'data'});
    +=> "Using 'with': no"
    + +

    + Precompiling your templates can be a big help when debugging errors you can't + reproduce. This is because precompiled templates can provide line numbers and + a stack trace, something that is not possible when compiling templates on the client. + The source property is available on the compiled template + function for easy precompilation. +

    + +
    <script>
    +  JST.project = <%= _.template(jstText).source %>;
    +</script>
    + + +

    Chaining

    + +

    + You can use Underscore in either an object-oriented or a functional style, + depending on your preference. The following two lines of code are + identical ways to double a list of numbers. +

    + +
    +_.map([1, 2, 3], function(n){ return n * 2; });
    +_([1, 2, 3]).map(function(n){ return n * 2; });
    + +

    + Calling chain will cause all future method calls to return + wrapped objects. When you've finished the computation, use + value to retrieve the final value. Here's an example of chaining + together a map/flatten/reduce, in order to get the word count of + every word in a song. +

    + +
    +var lyrics = [
    +  {line : 1, words : "I'm a lumberjack and I'm okay"},
    +  {line : 2, words : "I sleep all night and I work all day"},
    +  {line : 3, words : "He's a lumberjack and he's okay"},
    +  {line : 4, words : "He sleeps all night and he works all day"}
    +];
    +
    +_.chain(lyrics)
    +  .map(function(line) { return line.words.split(' '); })
    +  .flatten()
    +  .reduce(function(counts, word) {
    +    counts[word] = (counts[word] || 0) + 1;
    +    return counts;
    +}, {}).value();
    +
    +=> {lumberjack : 2, all : 4, night : 2 ... }
    + +

    + In addition, the + Array prototype's methods + are proxied through the chained Underscore object, so you can slip a + reverse or a push into your chain, and continue to + modify the array. +

    + +

    + chain_.chain(obj) +
    + Returns a wrapped object. Calling methods on this object will continue + to return wrapped objects until value is used. +

    +
    +var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
    +var youngest = _.chain(stooges)
    +  .sortBy(function(stooge){ return stooge.age; })
    +  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
    +  .first()
    +  .value();
    +=> "moe is 21"
    +
    + +

    + value_(obj).value() +
    + Extracts the value of a wrapped object. +

    +
    +_([1, 2, 3]).value();
    +=> [1, 2, 3]
    +
    + + + +

    + The Underscore documentation is also available in + Simplified Chinese. +

    + +

    + Underscore.lua, + a Lua port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + (source) +

    + +

    + Underscore.m, an Objective-C port + of many of the Underscore.js functions, using a syntax that encourages + chaining. + (source) +

    + +

    + _.m, an alternative + Objective-C port that tries to stick a little closer to the original + Underscore.js API. + (source) +

    + +

    + Underscore.php, + a PHP port of the functions that are applicable in both languages. + Includes OOP-wrapping and chaining. + (source) +

    + +

    + Underscore-perl, + a Perl port of many of the Underscore.js functions, + aimed at on Perl hashes and arrays. + (source) +

    + +

    + Underscore.cfc, + a Coldfusion port of many of the Underscore.js functions. + (source) +

    + +

    + Underscore.string, + an Underscore extension that adds functions for string-manipulation: + trim, startsWith, contains, capitalize, + reverse, sprintf, and more. +

    + +

    + Ruby's Enumerable module. +

    + +

    + Prototype.js, which provides + JavaScript with collection functions in the manner closest to Ruby's Enumerable. +

    + +

    + Oliver Steele's + Functional JavaScript, + which includes comprehensive higher-order function support as well as string lambdas. +

    + +

    + Michael Aufreiter's Data.js, + a data manipulation + persistence library for JavaScript. +

    + +

    + Python's itertools. +

    + +

    Change Log

    + +

    + 1.4.3Dec. 4, 2012Diff
    +

      +
    • + Improved Underscore compatibility with Adobe's JS engine that can be + used to script Illustrator, Photoshop, and friends. +
    • +
    • + Added a default _.identity iterator to countBy and + groupBy. +
    • +
    • + The uniq function can now take array, iterator, context + as the argument list. +
    • +
    • + The times function now returns the mapped array of iterator + results. +
    • +
    • + Simplified and fixed bugs in throttle. +
    • +
    +

    + +

    + 1.4.2Oct. 1, 2012Diff
    +

      +
    • + For backwards compatibility, returned to pre-1.4.0 behavior when + passing null to iteration functions. They now become no-ops + again. +
    • +
    +

    + +

    + 1.4.1Oct. 1, 2012Diff
    +

      +
    • + Fixed a 1.4.0 regression in the lastIndexOf function. +
    • +
    +

    + +

    + 1.4.0Sept. 27, 2012Diff
    +

      +
    • + Added a pairs function, for turning a JavaScript object + into [key, value] pairs ... as well as an object + function, for converting an array of [key, value] pairs + into an object. +
    • +
    • + Added a countBy function, for counting the number of objects + in a list that match a certain criteria. +
    • +
    • + Added an invert function, for performing a simple inversion + of the keys and values in an object. +
    • +
    • + Added a where function, for easy cases of filtering a list + for objects with specific values. +
    • +
    • + Added an omit function, for filtering an object to remove + certain keys. +
    • +
    • + Added a random function, to return a random number in a + given range. +
    • +
    • + _.debounce'd functions now return their last updated value, + just like _.throttle'd functions do. +
    • +
    • + The sortBy function now runs a stable sort algorithm. +
    • +
    • + Added the optional fromIndex option to indexOf and + lastIndexOf. +
    • +
    • + "Sparse" arrays are no longer supported in Underscore iteration + functions. Use a for loop instead (or better yet, an object). +
    • +
    • + The min and max functions may now be called on + very large arrays. +
    • +
    • + Interpolation in templates now represents null and + undefined as the empty string. +
    • +
    • + Underscore iteration functions no longer accept null values + as a no-op argument. You'll get an early error instead. +
    • +
    • + A number of edge-cases fixes and tweaks, which you can spot in the + diff. + Depending on how you're using Underscore, 1.4.0 may be more + backwards-incompatible than usual — please test when you upgrade. +
    • +
    +

    + +

    + 1.3.3April 10, 2012
    +

      +
    • + Many improvements to _.template, which now provides the + source of the template function as a property, for potentially + even more efficient pre-compilation on the server-side. You may now + also set the variable option when creating a template, + which will cause your passed-in data to be made available under the + variable you named, instead of using a with statement — + significantly improving the speed of rendering the template. +
    • +
    • + Added the pick function, which allows you to filter an + object literal with a whitelist of allowed property names. +
    • +
    • + Added the result function, for convenience when working + with APIs that allow either functions or raw properties. +
    • +
    • + Added the isFinite function, because sometimes knowing that + a value is a number just ain't quite enough. +
    • +
    • + The sortBy function may now also be passed the string name + of a property to use as the sort order on each object. +
    • +
    • + Fixed uniq to work with sparse arrays. +
    • +
    • + The difference function now performs a shallow flatten + instead of a deep one when computing array differences. +
    • +
    • + The debounce function now takes an immediate + parameter, which will cause the callback to fire on the leading + instead of the trailing edge. +
    • +
    +

    + +

    + 1.3.1Jan. 23, 2012
    +

      +
    • + Added an _.has function, as a safer way to use hasOwnProperty. +
    • +
    • + Added _.collect as an alias for _.map. Smalltalkers, rejoice. +
    • +
    • + Reverted an old change so that _.extend will correctly copy + over keys with undefined values again. +
    • +
    • + Bugfix to stop escaping slashes within interpolations in _.template. +
    • +
    +

    + +

    + 1.3.0Jan. 11, 2012
    +

      +
    • + Removed AMD (RequireJS) support from Underscore. If you'd like to use + Underscore with RequireJS, you can load it as a normal script, wrap + or patch your copy, or download a forked version. +
    • +
    +

    + +

    + 1.2.4Jan. 4, 2012
    +

      +
    • + You now can (and probably should, as it's simpler) + write _.chain(list) + instead of _(list).chain(). +
    • +
    • + Fix for escaped characters in Underscore templates, and for supporting + customizations of _.templateSettings that only define one or + two of the required regexes. +
    • +
    • + Fix for passing an array as the first argument to an _.wrap'd function. +
    • +
    • + Improved compatibility with ClojureScript, which adds a call + function to String.prototype. +
    • +
    +

    + +

    + 1.2.3Dec. 7, 2011
    +

      +
    • + Dynamic scope is now preserved for compiled _.template functions, + so you can use the value of this if you like. +
    • +
    • + Sparse array support of _.indexOf, _.lastIndexOf. +
    • +
    • + Both _.reduce and _.reduceRight can now be passed an + explicitly undefined value. (There's no reason why you'd + want to do this.) +
    • +
    +

    + +

    + 1.2.2Nov. 14, 2011
    +

      +
    • + Continued tweaks to _.isEqual semantics. Now JS primitives are + considered equivalent to their wrapped versions, and arrays are compared + by their numeric properties only (#351). +
    • +
    • + _.escape no longer tries to be smart about not double-escaping + already-escaped HTML entities. Now it just escapes regardless (#350). +
    • +
    • + In _.template, you may now leave semicolons out of evaluated + statements if you wish: <% }) %> (#369). +
    • +
    • + _.after(callback, 0) will now trigger the callback immediately, + making "after" easier to use with asynchronous APIs (#366). +
    • +
    +

    + +

    + 1.2.1Oct. 24, 2011
    +

      +
    • + Several important bug fixes for _.isEqual, which should now + do better on mutated Arrays, and on non-Array objects with + length properties. (#329) +
    • +
    • + jrburke contributed Underscore exporting for AMD module loaders, + and tonylukasavage for Appcelerator Titanium. + (#335, #338) +
    • +
    • + You can now _.groupBy(list, 'property') as a shortcut for + grouping values by a particular common property. +
    • +
    • + _.throttle'd functions now fire immediately upon invocation, + and are rate-limited thereafter (#170, #266). +
    • +
    • + Most of the _.is[Type] checks no longer ducktype. +
    • +
    • + The _.bind function now also works on constructors, a-la + ES5 ... but you would never want to use _.bind on a + constructor function. +
    • +
    • + _.clone no longer wraps non-object types in Objects. +
    • +
    • + _.find and _.filter are now the preferred names for + _.detect and _.select. +
    • +
    +

    + +

    + 1.2.0Oct. 5, 2011
    +

      +
    • + The _.isEqual function now + supports true deep equality comparisons, with checks for cyclic structures, + thanks to Kit Cambridge. +
    • +
    • + Underscore templates now support HTML escaping interpolations, using + <%- ... %> syntax. +
    • +
    • + Ryan Tenney contributed _.shuffle, which uses a modified + Fisher-Yates to give you a shuffled copy of an array. +
    • +
    • + _.uniq can now be passed an optional iterator, to determine by + what criteria an object should be considered unique. +
    • +
    • + _.last now takes an optional argument which will return the last + N elements of the list. +
    • +
    • + A new _.initial function was added, as a mirror of _.rest, + which returns all the initial values of a list (except the last N). +
    • +
    +

    + +

    + 1.1.7July 13, 2011
    + Added _.groupBy, which aggregates a collection into groups of like items. + Added _.union and _.difference, to complement the + (re-named) _.intersection. + Various improvements for support of sparse arrays. + _.toArray now returns a clone, if directly passed an array. + _.functions now also returns the names of functions that are present + in the prototype chain. +

    + +

    + 1.1.6April 18, 2011
    + Added _.after, which will return a function that only runs after + first being called a specified number of times. + _.invoke can now take a direct function reference. + _.every now requires an iterator function to be passed, which + mirrors the ECMA5 API. + _.extend no longer copies keys when the value is undefined. + _.bind now errors when trying to bind an undefined value. +

    + +

    + 1.1.5Mar 20, 2011
    + Added an _.defaults function, for use merging together JS objects + representing default options. + Added an _.once function, for manufacturing functions that should + only ever execute a single time. + _.bind now delegates to the native ECMAScript 5 version, + where available. + _.keys now throws an error when used on non-Object values, as in + ECMAScript 5. + Fixed a bug with _.keys when used over sparse arrays. +

    + +

    + 1.1.4Jan 9, 2011
    + Improved compliance with ES5's Array methods when passing null + as a value. _.wrap now correctly sets this for the + wrapped function. _.indexOf now takes an optional flag for + finding the insertion index in an array that is guaranteed to already + be sorted. Avoiding the use of .callee, to allow _.isArray + to work properly in ES5's strict mode. +

    + +

    + 1.1.3Dec 1, 2010
    + In CommonJS, Underscore may now be required with just:
    + var _ = require("underscore"). + Added _.throttle and _.debounce functions. + Removed _.breakLoop, in favor of an ECMA5-style un-break-able + each implementation — this removes the try/catch, and you'll now have + better stack traces for exceptions that are thrown within an Underscore iterator. + Improved the isType family of functions for better interoperability + with Internet Explorer host objects. + _.template now correctly escapes backslashes in templates. + Improved _.reduce compatibility with the ECMA5 version: + if you don't pass an initial value, the first item in the collection is used. + _.each no longer returns the iterated collection, for improved + consistency with ES5's forEach. +

    + +

    + 1.1.2
    + Fixed _.contains, which was mistakenly pointing at + _.intersect instead of _.include, like it should + have been. Added _.unique as an alias for _.uniq. +

    + +

    + 1.1.1
    + Improved the speed of _.template, and its handling of multiline + interpolations. Ryan Tenney contributed optimizations to many Underscore + functions. An annotated version of the source code is now available. +

    + +

    + 1.1.0
    + The method signature of _.reduce has been changed to match + the ECMAScript 5 signature, instead of the Ruby/Prototype.js version. + This is a backwards-incompatible change. _.template may now be + called with no arguments, and preserves whitespace. _.contains + is a new alias for _.include. +

    + +

    + 1.0.4
    + Andri Möll contributed the _.memoize + function, which can be used to speed up expensive repeated computations + by caching the results. +

    + +

    + 1.0.3
    + Patch that makes _.isEqual return false if any property + of the compared object has a NaN value. Technically the correct + thing to do, but of questionable semantics. Watch out for NaN comparisons. +

    + +

    + 1.0.2
    + Fixes _.isArguments in recent versions of Opera, which have + arguments objects as real Arrays. +

    + +

    + 1.0.1
    + Bugfix for _.isEqual, when comparing two objects with the same + number of undefined keys, but with different names. +

    + +

    + 1.0.0
    + Things have been stable for many months now, so Underscore is now + considered to be out of beta, at 1.0. Improvements since 0.6 + include _.isBoolean, and the ability to have _.extend + take multiple source objects. +

    + +

    + 0.6.0
    + Major release. Incorporates a number of + Mile Frawley's refactors for + safer duck-typing on collection functions, and cleaner internals. A new + _.mixin method that allows you to extend Underscore with utility + functions of your own. Added _.times, which works the same as in + Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray, + and Object.keys. +

    + +

    + 0.5.8
    + Fixed Underscore's collection functions to work on + NodeLists and + HTMLCollections + once more, thanks to + Justin Tulloss. +

    + +

    + 0.5.7
    + A safer implementation of _.isArguments, and a + faster _.isNumber,
    thanks to + Jed Schmidt. +

    + +

    + 0.5.6
    + Customizable delimiters for _.template, contributed by + Noah Sloan. +

    + +

    + 0.5.5
    + Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object. +

    + +

    + 0.5.4
    + Fix for multiple single quotes within a template string for + _.template. See: + Rick Strahl's blog post. +

    + +

    + 0.5.2
    + New implementations of isArray, isDate, isFunction, + isNumber, isRegExp, and isString, thanks to + a suggestion from + Robert Kieffer. + Instead of doing Object#toString + comparisons, they now check for expected properties, which is less safe, + but more than an order of magnitude faster. Most other Underscore + functions saw minor speed improvements as a result. + Evgeniy Dolzhenko + contributed _.tap, + similar to Ruby 1.9's, + which is handy for injecting side effects (like logging) into chained calls. +

    + +

    + 0.5.1
    + Added an _.isArguments function. Lots of little safety checks + and optimizations contributed by + Noah Sloan and + Andri Möll. +

    + +

    + 0.5.0
    + [API Changes] _.bindAll now takes the context object as + its first parameter. If no method names are passed, all of the context + object's methods are bound to it, enabling chaining and easier binding. + _.functions now takes a single argument and returns the names + of its Function properties. Calling _.functions(_) will get you + the previous behavior. + Added _.isRegExp so that isEqual can now test for RegExp equality. + All of the "is" functions have been shrunk down into a single definition. + Karl Guertin contributed patches. +

    + +

    + 0.4.7
    + Added isDate, isNaN, and isNull, for completeness. + Optimizations for isEqual when checking equality between Arrays + or Dates. _.keys is now 25%–2X faster (depending on your + browser) which speeds up the functions that rely on it, such as _.each. +

    + +

    + 0.4.6
    + Added the range function, a port of the + Python + function of the same name, for generating flexibly-numbered lists + of integers. Original patch contributed by + Kirill Ishanov. +

    + +

    + 0.4.5
    + Added rest for Arrays and arguments objects, and aliased + first as head, and rest as tail, + thanks to Luke Sutton's patches. + Added tests ensuring that all Underscore Array functions also work on + arguments objects. +

    + +

    + 0.4.4
    + Added isString, and isNumber, for consistency. Fixed + _.isEqual(NaN, NaN) to return true (which is debatable). +

    + +

    + 0.4.3
    + Started using the native StopIteration object in browsers that support it. + Fixed Underscore setup for CommonJS environments. +

    + +

    + 0.4.2
    + Renamed the unwrapping function to value, for clarity. +

    + +

    + 0.4.1
    + Chained Underscore objects now support the Array prototype methods, so + that you can perform the full range of operations on a wrapped array + without having to break your chain. Added a breakLoop method + to break in the middle of any Underscore iteration. Added an + isEmpty function that works on arrays and objects. +

    + +

    + 0.4.0
    + All Underscore functions can now be called in an object-oriented style, + like so: _([1, 2, 3]).map(...);. Original patch provided by + Marc-André Cournoyer. + Wrapped objects can be chained through multiple + method invocations. A functions method + was added, providing a sorted list of all the functions in Underscore. +

    + +

    + 0.3.3
    + Added the JavaScript 1.8 function reduceRight. Aliased it + as foldr, and aliased reduce as foldl. +

    + +

    + 0.3.2
    + Now runs on stock Rhino + interpreters with: load("underscore.js"). + Added identity as a utility function. +

    + +

    + 0.3.1
    + All iterators are now passed in the original collection as their third + argument, the same as JavaScript 1.6's forEach. Iterating over + objects is now called with (value, key, collection), for details + see _.each. +

    + +

    + 0.3.0
    + Added Dmitry Baranovskiy's + comprehensive optimizations, merged in + Kris Kowal's patches to make Underscore + CommonJS and + Narwhal compliant. +

    + +

    + 0.2.0
    + Added compose and lastIndexOf, renamed inject to + reduce, added aliases for inject, filter, + every, some, and forEach. +

    + +

    + 0.1.1
    + Added noConflict, so that the "Underscore" object can be assigned to + other variables. +

    + +

    + 0.1.0
    + Initial release of Underscore.js. +

    + +

    + + A DocumentCloud Project + +

    + +
    + +
    + + + + + + diff --git a/node_modules/underscore/index.js b/node_modules/underscore/index.js new file mode 100644 index 0000000..2cf0ca5 --- /dev/null +++ b/node_modules/underscore/index.js @@ -0,0 +1 @@ +module.exports = require('./underscore'); diff --git a/node_modules/underscore/package.json b/node_modules/underscore/package.json new file mode 100644 index 0000000..330ae77 --- /dev/null +++ b/node_modules/underscore/package.json @@ -0,0 +1,28 @@ +{ + "name": "underscore", + "description": "JavaScript's functional programming helper library.", + "homepage": "http://underscorejs.org", + "keywords": [ + "util", + "functional", + "server", + "client", + "browser" + ], + "author": { + "name": "Jeremy Ashkenas", + "email": "jeremy@documentcloud.org" + }, + "repository": { + "type": "git", + "url": "git://github.com/documentcloud/underscore.git" + }, + "main": "underscore.js", + "version": "1.4.3", + "readme": " __\n /\\ \\ __\n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____\n /\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\\n \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/\n \\ \\____/\n \\/___/\n\nUnderscore.js is a utility-belt library for JavaScript that provides\nsupport for the usual functional suspects (each, map, reduce, filter...)\nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://underscorejs.org\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n", + "_id": "underscore@1.4.3", + "dist": { + "shasum": "b3d0aaa1ee74d886ea4f2648021a4f8ad779ed1d" + }, + "_from": "underscore" +} diff --git a/node_modules/underscore/raw/underscore.psd b/node_modules/underscore/raw/underscore.psd new file mode 100644 index 0000000..73ad2d7 Binary files /dev/null and b/node_modules/underscore/raw/underscore.psd differ diff --git a/node_modules/underscore/underscore-min.js b/node_modules/underscore/underscore-min.js new file mode 100644 index 0000000..7ed6e52 --- /dev/null +++ b/node_modules/underscore/underscore-min.js @@ -0,0 +1 @@ +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,v=e.reduce,h=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.3";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduce===v)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduceRight===h)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?-1!=n.indexOf(t):E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2);return w.map(n,function(n){return(w.isFunction(t)?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t){return w.isEmpty(t)?[]:w.filter(n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var F=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=F(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i};var I=function(){};w.bind=function(n,t){var r,e;if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));if(!w.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));I.prototype=n.prototype;var u=new I;I.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},w.bindAll=function(n){var t=o.call(arguments,1);return 0==t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=S(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&S(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return S(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),w.isFunction=function(n){return"function"==typeof n},w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return void 0===n},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+(0|Math.random()*(t-n+1))};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};T.unescape=w.invert(T.escape);var M={escape:RegExp("["+w.keys(T.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(T.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(M[n],function(t){return T[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=""+ ++N;return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){r=w.defaults({},r,w.templateSettings);var e=RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,a,o){return i+=n.slice(u,o).replace(D,function(n){return"\\"+B[n]}),r&&(i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(i+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),a&&(i+="';\n"+a+"\n__p+='"),u=o+t.length,t}),i+="';\n",r.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var a=Function(r.variable||"obj","_",i)}catch(o){throw o.source=i,o}if(t)return a(t,w);var c=function(n){return a.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+i+"}",c},w.chain=function(n){return w(n).chain()};var z=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff --git a/node_modules/underscore/underscore.js b/node_modules/underscore/underscore.js new file mode 100644 index 0000000..4d83099 --- /dev/null +++ b/node_modules/underscore/underscore.js @@ -0,0 +1,1221 @@ +// Underscore.js 1.4.3 +// http://underscorejs.org +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.4.3'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (_.isFunction(method) ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // with specific `key:value` pairs. + _.where = function(obj, attrs) { + if (_.isEmpty(attrs)) return []; + return _.filter(obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See: https://bugs.webkit.org/show_bug.cgi?id=80797 + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + index : index, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value || _.identity); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + }; + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + each(input, function(value) { + if (_.isArray(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(concat.apply(ArrayProto, arguments)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(args, "" + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, l = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function(func, context) { + var args, bound; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, result; + var previous = 0; + var later = function() { + previous = new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(n); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + (0 | Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = '' + ++idCounter; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + +}).call(this); diff --git a/package.json b/package.json new file mode 100644 index 0000000..3aa58c7 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "specs-crepe", + "version": "0.0.1", + "private": true, + "scripts": { + "start": "node app" + }, + "dependencies": { + "express": "3.1.0", + "jade": "*" + } +} \ No newline at end of file diff --git a/public/css/bootstrap-responsive.css b/public/css/bootstrap-responsive.css new file mode 100644 index 0000000..5215a5d --- /dev/null +++ b/public/css/bootstrap-responsive.css @@ -0,0 +1,1109 @@ +/*! + * Bootstrap Responsive v2.3.0 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +@-ms-viewport { + width: device-width; +} + +.hidden { + display: none; + visibility: hidden; +} + +.visible-phone { + display: none !important; +} + +.visible-tablet { + display: none !important; +} + +.hidden-desktop { + display: none !important; +} + +.visible-desktop { + display: inherit !important; +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important ; + } + .visible-tablet { + display: inherit !important; + } + .hidden-tablet { + display: none !important; + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + .visible-desktop { + display: none !important; + } + .visible-phone { + display: inherit !important; + } + .hidden-phone { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: inherit !important; + } + .hidden-print { + display: none !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + .span12 { + width: 1170px; + } + .span11 { + width: 1070px; + } + .span10 { + width: 970px; + } + .span9 { + width: 870px; + } + .span8 { + width: 770px; + } + .span7 { + width: 670px; + } + .span6 { + width: 570px; + } + .span5 { + width: 470px; + } + .span4 { + width: 370px; + } + .span3 { + width: 270px; + } + .span2 { + width: 170px; + } + .span1 { + width: 70px; + } + .offset12 { + margin-left: 1230px; + } + .offset11 { + margin-left: 1130px; + } + .offset10 { + margin-left: 1030px; + } + .offset9 { + margin-left: 930px; + } + .offset8 { + margin-left: 830px; + } + .offset7 { + margin-left: 730px; + } + .offset6 { + margin-left: 630px; + } + .offset5 { + margin-left: 530px; + } + .offset4 { + margin-left: 430px; + } + .offset3 { + margin-left: 330px; + } + .offset2 { + margin-left: 230px; + } + .offset1 { + margin-left: 130px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975%; + } + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212%; + } + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266%; + } + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411%; + } + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556%; + } + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014%; + } + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847%; + } + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924%; + } + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375%; + } + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828%; + } + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281%; + } + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171%; + } + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915%; + } + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316%; + } + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061%; + } + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462%; + } + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206%; + } + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607%; + } + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352%; + } + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753%; + } + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497%; + } + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899%; + } + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642%; + } + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444%; + } + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875%; + } + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219%; + } + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933%; + } + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354%; + } + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785%; + } + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048%; + } + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224%; + } + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257%; + } + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369%; + } + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708%; + } + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + .thumbnails { + margin-left: -30px; + } + .thumbnails > li { + margin-left: 30px; + } + .row-fluid .thumbnails { + margin-left: 0; + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + .row:after { + clear: both; + } + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + .span12 { + width: 724px; + } + .span11 { + width: 662px; + } + .span10 { + width: 600px; + } + .span9 { + width: 538px; + } + .span8 { + width: 476px; + } + .span7 { + width: 414px; + } + .span6 { + width: 352px; + } + .span5 { + width: 290px; + } + .span4 { + width: 228px; + } + .span3 { + width: 166px; + } + .span2 { + width: 104px; + } + .span1 { + width: 42px; + } + .offset12 { + margin-left: 764px; + } + .offset11 { + margin-left: 702px; + } + .offset10 { + margin-left: 640px; + } + .offset9 { + margin-left: 578px; + } + .offset8 { + margin-left: 516px; + } + .offset7 { + margin-left: 454px; + } + .offset6 { + margin-left: 392px; + } + .offset5 { + margin-left: 330px; + } + .offset4 { + margin-left: 268px; + } + .offset3 { + margin-left: 206px; + } + .offset2 { + margin-left: 144px; + } + .offset1 { + margin-left: 82px; + } + .row-fluid { + width: 100%; + *zoom: 1; + } + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + .row-fluid:after { + clear: both; + } + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194%; + } + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608%; + } + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387%; + } + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166%; + } + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946%; + } + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725%; + } + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504%; + } + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283%; + } + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062%; + } + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841%; + } + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199%; + } + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988%; + } + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962%; + } + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031%; + } + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274%; + } + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089%; + } + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252%; + } + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868%; + } + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299%; + } + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647%; + } + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079%; + } + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427%; + } + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584%; + } + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065%; + } + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376%; + } + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986%; + } + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417%; + } + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765%; + } + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196%; + } + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544%; + } + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746%; + } + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227%; + } + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537%; + } + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102%; + } + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325%; + } + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806%; + } + input, + textarea, + .uneditable-input { + margin-left: 0; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px; + } + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-right: -20px; + margin-left: -20px; + } + .container-fluid { + padding: 0; + } + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left; + } + .dl-horizontal dd { + margin-left: 0; + } + .container { + width: auto; + } + .row-fluid { + width: 100%; + } + .row, + .thumbnails { + margin-left: 0; + } + .thumbnails > li { + float: none; + margin-left: 0; + } + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0; + } + .modal.fade { + top: -100px; + } + .modal.fade.in { + top: 20px; + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + .page-header h1 small { + display: block; + line-height: 20px; + } + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + .form-horizontal .controls { + margin-left: 0; + } + .form-horizontal .control-list { + padding-top: 0; + } + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px; + } + .media .pull-left, + .media .pull-right { + display: block; + float: none; + margin-bottom: 10px; + } + .media-object { + margin-right: 0; + margin-left: 0; + } + .modal { + top: 10px; + right: 10px; + left: 10px; + } + .modal-header .close { + padding: 10px; + margin: -10px; + } + .carousel-caption { + position: static; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + .navbar-fixed-top { + margin-bottom: 20px; + } + .navbar-fixed-bottom { + margin-top: 20px; + } + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + .navbar .container { + width: auto; + padding: 0; + } + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px; + } + .nav-collapse { + clear: both; + } + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + .nav-collapse .nav > li { + float: none; + } + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + .nav-collapse .nav > .divider-vertical { + display: none; + } + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + .nav-collapse .nav > li > a:hover, + .nav-collapse .nav > li > a:focus, + .nav-collapse .dropdown-menu a:hover, + .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2; + } + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .nav > li > a:focus, + .navbar-inverse .nav-collapse .dropdown-menu a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111111; + } + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px; + } + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + .nav-collapse .open > .dropdown-menu { + display: block; + } + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + .nav-collapse .dropdown-menu .divider { + display: none; + } + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + .nav-collapse, + .nav-collapse.collapse { + height: 0; + overflow: hidden; + } + .navbar .btn-navbar { + display: block; + } + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} diff --git a/public/css/bootstrap-responsive.min.css b/public/css/bootstrap-responsive.min.css new file mode 100644 index 0000000..0597860 --- /dev/null +++ b/public/css/bootstrap-responsive.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap Responsive v2.3.0 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff --git a/public/css/bootstrap.css b/public/css/bootstrap.css new file mode 100644 index 0000000..b255056 --- /dev/null +++ b/public/css/bootstrap.css @@ -0,0 +1,6158 @@ +/*! + * Bootstrap v2.3.0 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img, +.google-maps img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover, +a:focus { + color: #005580; + text-decoration: underline; +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + line-height: 0; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} + +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.127659574468085%; +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594%; +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361%; +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126%; +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893%; +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659%; +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425%; +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192%; +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576%; +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233%; +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894%; +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553%; +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275%; +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467%; +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404%; +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232%; +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807%; +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999%; +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572%; +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764%; +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339%; +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553%; +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106%; +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297%; +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715%; +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063%; +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638%; +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383%; +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405%; +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596%; +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617%; +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618%; +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936%; +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278%; +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702%; +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938%; +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + line-height: 0; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} + +small { + font-size: 85%; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +cite { + font-style: normal; +} + +.muted { + color: #999999; +} + +a.muted:hover, +a.muted:focus { + color: #808080; +} + +.text-warning { + color: #c09853; +} + +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c; +} + +.text-error { + color: #b94a48; +} + +a.text-error:hover, +a.text-error:focus { + color: #953b39; +} + +.text-info { + color: #3a87ad; +} + +a.text-info:hover, +a.text-info:focus { + color: #2d6987; +} + +.text-success { + color: #468847; +} + +a.text-success:hover, +a.text-success:focus { + color: #356635; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + line-height: 40px; +} + +h1 { + font-size: 38.5px; +} + +h2 { + font-size: 31.5px; +} + +h3 { + font-size: 24.5px; +} + +h4 { + font-size: 17.5px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 11.9px; +} + +h1 small { + font-size: 24.5px; +} + +h2 small { + font-size: 17.5px; +} + +h3 small { + font-size: 14px; +} + +h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + padding: 0; + margin: 0 0 10px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +li { + line-height: 20px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +ul.inline, +ol.inline { + margin-left: 0; + list-style: none; +} + +ul.inline > li, +ol.inline > li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 10px; +} + +.dl-horizontal { + *zoom: 1; +} + +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + line-height: 0; + content: ""; +} + +.dl-horizontal:after { + clear: both; +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 180px; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote small { + display: block; + line-height: 20px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 20px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 15px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +input, +textarea, +.uneditable-input { + width: 206px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal; +} + +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +select, +input[type="file"] { + height: 30px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 30px; +} + +select { + width: 220px; + background-color: #ffffff; + border: 1px solid #cccccc; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.uneditable-input, +.uneditable-textarea { + color: #999999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} + +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px; +} + +.controls-row { + *zoom: 1; +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: ""; +} + +.controls-row:after { + clear: both; +} + +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left; +} + +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; +} + +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; +} + +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; +} + +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad; +} + +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad; +} + +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; +} + +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad; +} + +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + line-height: 0; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.help-block, +.help-inline { + color: #595959; +} + +.help-block { + display: block; + margin-bottom: 10px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2; +} + +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group > .dropdown-toggle, +.input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input + .btn-group .btn:last-child, +.input-append select + .btn-group .btn:last-child, +.input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append input + .btn-group .btn, +.input-prepend.input-append select + .btn-group .btn, +.input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0; +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +/* Allow for input prepend/append in search forms */ + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 10px; +} + +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + line-height: 0; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 180px; +} + +.form-horizontal .help-block { + margin-bottom: 0; +} + +.form-horizontal input + .help-block, +.form-horizontal select + .help-block, +.form-horizontal textarea + .help-block, +.form-horizontal .uneditable-input + .help-block, +.form-horizontal .input-prepend + .help-block, +.form-horizontal .input-append + .help-block { + margin-top: 10px; +} + +.form-horizontal .form-actions { + padding-left: 180px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child > th:first-child, +.table-bordered tbody:first-child tr:first-child > td:first-child, +.table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child > th:last-child, +.table-bordered tbody:first-child tr:first-child > td:last-child, +.table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:first-child, +.table-bordered tbody:last-child tr:last-child > td:first-child, +.table-bordered tbody:last-child tr:last-child > th:first-child, +.table-bordered tfoot:last-child tr:last-child > td:first-child, +.table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:last-child, +.table-bordered tbody:last-child tr:last-child > td:last-child, +.table-bordered tbody:last-child tr:last-child > th:last-child, +.table-bordered tfoot:last-child tr:last-child > td:last-child, +.table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0; +} + +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-striped tbody > tr:nth-child(odd) > td, +.table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover tbody tr:hover > td, +.table-hover tbody tr:hover > th { + background-color: #f5f5f5; +} + +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0; +} + +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0; +} + +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0; +} + +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0; +} + +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0; +} + +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0; +} + +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0; +} + +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0; +} + +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0; +} + +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0; +} + +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0; +} + +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0; +} + +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0; +} + +.table tbody tr.success > td { + background-color: #dff0d8; +} + +.table tbody tr.error > td { + background-color: #f2dede; +} + +.table tbody tr.warning > td { + background-color: #fcf8e3; +} + +.table tbody tr.info > td { + background-color: #d9edf7; +} + +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6; +} + +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc; +} + +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc; +} + +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +/* White icons with optional class, or on hover/focus/active states of certain elements */ + +.icon-white, +.nav-pills > .active > a > [class^="icon-"], +.nav-pills > .active > a > [class*=" icon-"], +.nav-list > .active > a > [class^="icon-"], +.nav-list > .active > a > [class*=" icon-"], +.navbar-inverse .nav > .active > a > [class^="icon-"], +.navbar-inverse .nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:focus > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > li > a:focus > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:focus > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"], +.dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + width: 16px; + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px; +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-submenu:hover > a, +.dropdown-submenu:focus > a { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} + +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0; +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #cccccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " "; +} + +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px; +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px; +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} + +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn-primary { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #0044cc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #003399 \9; +} + +.btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #ffffff; + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #ffffff; + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #ffffff; + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #ffffff; + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222222; + background-image: -moz-linear-gradient(top, #444444, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #ffffff; + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-link { + color: #0088cc; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333333; + text-decoration: none; +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn + .btn { + margin-left: -1px; +} + +.btn-group > .btn, +.btn-group > .dropdown-menu, +.btn-group > .popover { + font-size: 14px; +} + +.btn-group > .btn-mini { + font-size: 10.5px; +} + +.btn-group > .btn-small { + font-size: 11.9px; +} + +.btn-group > .btn-large { + font-size: 17.5px; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px; +} + +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0044cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 8px; + margin-left: 0; +} + +.btn-large .caret { + margin-top: 6px; +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px; +} + +.dropup .btn-large .caret { + border-bottom-width: 5px; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group-vertical > .btn + .btn { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert, +.alert h4 { + color: #c09853; +} + +.alert h4 { + margin: 0; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success h4 { + color: #468847; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger h4, +.alert-error h4 { + color: #b94a48; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info h4 { + color: #3a87ad; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li > a > img { + max-width: none; +} + +.nav > .pull-right { + float: right; +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover, +.nav-list > .active > a:focus { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + line-height: 0; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover, +.nav-tabs > .active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover, +.nav-pills > .active > a:focus { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.nav-tabs.nav-stacked > li > a:hover, +.nav-tabs.nav-stacked > li > a:focus { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +/* move down carets for tabs */ + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.nav > .dropdown.active > a:hover, +.nav > .dropdown.active > a:focus { + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover, +.nav > li.dropdown.open.active > a:focus { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover, +.tabs-stacked .open > a:focus { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + line-height: 0; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover, +.tabs-below > .nav-tabs > li > a:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover, +.tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover, +.tabs-left > .nav-tabs > li > a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover, +.tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover, +.tabs-right > .nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover, +.tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover, +.nav > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); +} + +.navbar-inner:before, +.navbar-inner:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-inner:after { + clear: both; +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; + overflow: visible; +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777777; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none; +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} + +.navbar-link { + color: #777777; +} + +.navbar-link:hover, +.navbar-link:focus { + color: #333333; +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #ffffff; + border-left: 1px solid #f2f2f2; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.navbar-static-top { + position: static; + margin-bottom: 0; +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px; +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0; +} + +.navbar .nav > li { + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777777; + text-decoration: none; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; +} + +.navbar .nav > li > a:focus, +.navbar .nav > li > a:hover { + color: #333333; + text-decoration: none; + background-color: transparent; +} + +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #cccccc \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .nav > li > .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .nav > li > .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown > a:hover .caret, +.navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555555; + background-color: #e5e5e5; +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #ffffff; +} + +.navbar-inverse .brand { + color: #999999; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #ffffff; +} + +.navbar-inverse .divider-vertical { + border-right-color: #222222; + border-left-color: #111111; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .nav li.dropdown > a:hover .caret, +.navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + margin: 20px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination ul > li { + display: inline; +} + +.pagination ul > li > a, +.pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + border-left-width: 0; +} + +.pagination ul > li > a:hover, +.pagination ul > li > a:focus, +.pagination ul > .active > a, +.pagination ul > .active > span { + background-color: #f5f5f5; +} + +.pagination ul > .active > a, +.pagination ul > .active > span { + color: #999999; + cursor: default; +} + +.pagination ul > .disabled > span, +.pagination ul > .disabled > a, +.pagination ul > .disabled > a:hover, +.pagination ul > .disabled > a:focus { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination ul > li:first-child > a, +.pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.pagination ul > li:last-child > a, +.pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pagination-large ul > li > a, +.pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px; +} + +.pagination-large ul > li:first-child > a, +.pagination-large ul > li:first-child > span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.pagination-large ul > li:last-child > a, +.pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.pagination-mini ul > li:first-child > a, +.pagination-small ul > li:first-child > a, +.pagination-mini ul > li:first-child > span, +.pagination-small ul > li:first-child > span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px; +} + +.pagination-mini ul > li:last-child > a, +.pagination-small ul > li:last-child > a, +.pagination-mini ul > li:last-child > span, +.pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; +} + +.pagination-small ul > li > a, +.pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px; +} + +.pagination-mini ul > li > a, +.pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px; +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + line-height: 0; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.popover-title:empty { + display: none; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + line-height: 0; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #555555; +} + +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + margin-left: 0; + list-style: none; +} + +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +.label:empty, +.badge:empty { + display: none; +} + +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} + +.btn-mini .label, +.btn-mini .badge { + top: 0; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); +} + +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); +} + +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); +} + +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); +} + +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 20px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none; +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + line-height: 20px; + color: #ffffff; +} + +.carousel-caption h4 { + margin: 0 0 5px; +} + +.carousel-caption p { + margin-bottom: 0; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit li { + line-height: 30px; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} + +.affix { + position: fixed; +} diff --git a/public/css/bootstrap.min.css b/public/css/bootstrap.min.css new file mode 100644 index 0000000..fd5ed73 --- /dev/null +++ b/public/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.0 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/public/css/codemirror.css b/public/css/codemirror.css new file mode 100644 index 0000000..1ceb080 --- /dev/null +++ b/public/css/codemirror.css @@ -0,0 +1,240 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; +} +.CodeMirror-scroll { + /* Set scrolling behaviour here */ + overflow: auto; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; +} + +/* CURSOR */ + +.CodeMirror div.CodeMirror-cursor { + border-left: 1px solid black; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { + width: auto; + border: 0; + background: transparent; + background: rgba(0, 200, 0, .4); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800); +} +/* Kludge to turn off filter in ie9+, which also accepts rgba */ +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) { + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} + +/* DEFAULT THEME */ + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable {color: black;} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-property {color: black;} +.cm-s-default .cm-operator {color: black;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-error {color: #f00;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-emstrong {font-style: italic; font-weight: bold;} +.cm-link {text-decoration: underline;} + +.cm-invalidchar {color: #f00;} + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + line-height: 1; + position: relative; + overflow: hidden; +} + +.CodeMirror-scroll { + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; padding-right: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actuall scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; + z-index: 6; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + height: 100%; + z-index: 3; +} +.CodeMirror-gutter { + height: 100%; + display: inline-block; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} + +.CodeMirror-lines { + cursor: text; +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-wrap .CodeMirror-scroll { + overflow-x: hidden; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; height: 0px; + overflow: hidden; + visibility: hidden; +} +.CodeMirror-measure pre { position: static; } + +.CodeMirror div.CodeMirror-cursor { + position: absolute; + visibility: hidden; + border-right: none; + width: 0; +} +.CodeMirror-focused div.CodeMirror-cursor { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursor { + visibility: hidden; + } +} diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..f5d87a0 --- /dev/null +++ b/public/css/style.css @@ -0,0 +1,166 @@ +#results { display:none; } + +#image { width:70%; margin:0 auto; display:block; } +#html { width:90%; height:400px; font-size:0.9em; font-family:Consolas,monospace; display:block; margin:0 auto; } +h3 { text-align:center; padding-bottom:0.8em; } +#modal-trigger { display:block; margin:1em auto; } + + + + + +/* ============================================================================= + Gallery ('Lightbox') + ========================================================================== */ + +.gallery-hidden { display: none !important; } + +#gallery-overlay { + width: 100%; + height: 100%; + background-color: #000; + position: fixed; + top: 0px; + left: 0px; + display: none; + zoom: 1; + filter: alpha(opacity=50); + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50); + opacity: 0.5; + cursor: pointer; + z-index: 1010; +} +.hidden-main#gallery-overlay, .hidden-main#gallery-modal { display: none; filter: alpha(opacity=0); opacity: 0; } +#gallery-modal { width: 570px; height: 580px; background-color: #fff; position: relative; display: none; z-index: 1011; } +#gallery-modal h3 { padding: 25px 0px 0px 25px; height: 45px; border-bottom: 1px solid #dedede; background-color: #fafafa; display: block; margin: 0px; font: bold 21px/21px Arial, sans-serif; } +#gallery-modal .gallery-content { height: 445px; width: 570px; overflow: auto; padding-bottom: 25px; } +.lt-ie9 #gallery-modal .gallery-content { overflow-x: hidden; height: 455px; } +#gallery-modal .gallery-content #movideo-holder { width: 100%; height: 306px; } +#gallery-modal .gallery-content img.gallery-media { width: 100%; height: auto;} +/*.lt-ie8 #gallery-modal .gallery-content #movideo-holder, .lt-ie8 #gallery-modal .gallery-content img.gallery-media { width: 553px; }*/ +#gallery-modal .gallery-content p { font: normal 15px/17px Arial, sans-serif; color: #707070; margin: 25px 25px 0px 25px;} +.gallery-content ul { font: normal 15px/17px Arial, sans-serif; color: #707070; margin: 0px 25px 0px 0px;} +#gallery-modal .gallery-footer { padding: 28px 90px 0px 0px; height: 47px; border-top: 1px solid #dedede; background-color: #fafafa; display: block; margin: 0px; text-align: right; font: normal 13px/13px Arial, sans-serif; color: #707070; } +#gallery-modal a.prev, #gallery-modal a.next { position: absolute; bottom: -5px; background: url(http://www.mazda.com.au/brochures/base-framework/img/gallery/btn-gallery-nav.png) no-repeat; width: 25px; height: 27px; display: block; border: none; outline: none; } + +#gallery-modal a.prev { background-position: left 0px; right: 54px; } +#gallery-modal a.next { background-position: right 0px; right: 30px; } +#gallery-modal a.prev:hover { background-position: left 50%; } +#gallery-modal a.next:hover { background-position: right 50%; } +.ios #gallery-modal a.prev:hover { background-position: left 0px; } +.ios #gallery-modal a.next:hover { background-position: right 0px; } +#gallery-modal a.prev:active { background-position: left 100%; } +#gallery-modal a.next:active { background-position: right 100%; } +#gallery-modal a.prev.disabled, #gallery-modal a.next.disabled { filter: alpha(opacity=50); opacity: 0.5; cursor: default!important; } +#gallery-modal a.prev.disabled { background-position: left 0px;} +#gallery-modal a.next.disabled { background-position: right 0px;} +#gallery-modal a.prev.hide { display: none; } +#gallery-modal a.next.hide { display: none; } +#gallery-modal span.slash.hide { display: none; } +#gallery-modal a.close { position: absolute; top: -12px; right: -12px; background: url(http://www.mazda.com.au/brochures/base-framework/img/gallery/btn-gallery-close.png) center 0px no-repeat; width: 25px; height: 25px; display: block; opacity:1; } +#gallery-modal a.close:hover { background-position: 0px -25px; } +#gallery-modal a.close:active { background-position: 0px -50px; } + +#gallery-modal .gallery-content .warranty { display: none; } + +/** Lightbox Fullscreen Video Styling **/ +.fullscreen#gallery-modal { width: 924px; height: 520px; background-color: #000;} +.fullscreen#gallery-modal#gallery-modal h3, .fullscreen#gallery-modal .gallery-footer, .fullscreen#gallery-modal a.prev, .fullscreen#gallery-modal a.next { position: relative; display: none; } +.fullscreen#gallery-modal .gallery-content { width: 924px; height: 520px; padding: 0px; margin: 0px; overflow: hidden;} +.fullscreen#gallery-modal a.close { top: 10px; right: -35px; } +.fullscreen#gallery-modal .gallery-content #movideo-holder, .lt-ie8 .fullscreen#gallery-modal .gallery-content #movideo-holder, .lt-ie8 .fullscreen#gallery-modal .gallery-content img.gallery-media { width: 924px; height: 520px; } + + +.mobile-phone .fullscreen#gallery-modal a.close { background: url(http://www.mazda.com.au/brochures/base-framework/img/buttons/icon_close_phone.png); width: 50px; height: 48px; display: block; right: -60px;} + + +/** Lightbox Spec Styling **/ +#specs { display: none; } +.specs #specs { display: block; } +.specs-loading#gallery-modal, +.specs#gallery-modal { width: 781px; height: 600px; background-color: #262626;} +.specs#gallery-modal h3, .specs-loading#gallery-modal h3, +.specs#gallery-modal .gallery-content, .specs-loading#gallery-modal .gallery-content, +.specs#gallery-modal .gallery-footer, .specs-loading#gallery-modal .gallery-footer, +.specs#gallery-modal a.prev, .specs-loading#gallery-modal a.prev, +.specs#gallery-modal a.next, .specs-loading#gallery-modal a.next { position: relative; display: none; } +.specs#gallery-modal a.close, .specs-loading#gallery-modal a.close { top: 10px; right: 10px; } +.specs-loading #specs-loading { padding-top: 280px; color: white; text-align: center; font-weight: bold; } + +/*.specs#gallery-modal table.table-headings, .specs#gallery-modal table.table-headings tr, .specs#gallery-modal table.table-headings th { height: 45px; } +.specs#gallery-modal table.table-headings tr th { width: 120px; } +.specs#gallery-modal table.table-headings tr th.tab-class { width: 185px;}*/ + +.specs#gallery-modal table tr td.empty { height: 16px;} +.specs#gallery-modal table tr th.smalllineheight { line-height: 15px;} + +.specsoverflow { overflow: auto; width: 766px; height: 318px; background-color: #fff; } + + +/* ============================================================================= + Specs Table + ========================================================================== */ + +#specs {background:url(http://www.mazda.com.au/brochures/base-framework/img/specs/bg_specs.jpg) 0px 0px repeat-x #262626;} + +#specifications-module {width:766px; margin: 0px auto; background:url(http://www.mazda.com.au/brochures/base-framework/img/specs/bg_specs.jpg) 0px 0px repeat-x #262626;} +#specifications-module .specifications-set { width: 766px; } +#specifications-module.fwd .specifications-set.fwd { display: block; } +#specifications-module.awd .specifications-set.awd { display: block; } + +ul.tab-set { list-style-type: none; width:746px; margin: 30px auto; padding: 0px;} +ul.tab-set li { float: left; width:369px; margin-right:8px;} +ul.tab-set li.single { width: 738px; } +ul.tab-set li img { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)"; + filter: alpha(opacity=20); + opacity: .2; + + -webkit-transition: all .5s ease; + -moz-transition: all .5s ease; + -o-transition: all .5s ease; + -ms-transition: all .5s ease; + transition: all .5s ease; +} +ul.tab-set li:hover img, ul.tab-set li.current img { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; + filter: alpha(opacity=100); + opacity: 1; +} + +ul.tab-set li.last {margin-right: 0px;} +ul.tab-set li a {width:369px; display: block; outline: none; border: 0;} +ul.tab-set li.single a {width:738px; } +ul.tab-set li a, ul.tab-set li a:focus, ul.tab-set li a:active { outline: none; } +ul.tab-set li a span {margin-top:7px; display: block; width: 369px; border-top:4px solid #999999; color: #999999; font:bold 14px/14px arial, helvetica, sans-serif; padding-top:5px;} +ul.tab-set li.single a span { width: 738px; } +ul.tab-set li.current a span { color: #0083d1; border-color: #0083d1; } + +ul.table-tabs { list-style-type: none; margin: 0px; padding: 0px; width: 766px; } +ul.table-tabs li {float: left; margin-right: 1px; background:url(http://www.mazda.com.au/brochures/base-framework/img/specs/specstabletabsbgleft.jpg) 0px 0px no-repeat; height: 32px;} +ul.table-tabs li a {height: 32px; display: block; padding:0px 17px; background: url(http://www.mazda.com.au/brochures/base-framework/img/specs/specstabletabsbgright.jpg) top right no-repeat; color: #ffffff; font:13px/32px arial, helvetica, sans-serif;} +ul.table-tabs li.current {background:url(http://www.mazda.com.au/brochures/base-framework/img/specs/statstabletabsbgcurrentleft.jpg) 0px 0px no-repeat;} +ul.table-tabs li.current a {background: url(http://www.mazda.com.au/brochures/base-framework/img/specs/statstabletabsbgcurrentright.jpg) top right no-repeat;} + +.specifications-set { display: none; } +.specifications-set table { width: 742px; background-color: #ffffff; display: none;} +.specifications-set table tr th {background-color:#ffffff; padding: 15px 10px; color: #000000; font:12px arial, helvetica, sans-serif; width:150px;margin: 1px;} +.specifications-set table tr th.stat { vertical-align: top; line-height: 1.3em; } +.specifications-set table tr.zebra {background-color: #eff6fc;} +.specifications-set table tr {background-color: #f7fbfe; font-size:12px;} +.specifications-set#awd table tr .tab-class {width: 190px;} +.two-col table tr .tab-class {width: 422px;} +.no-textshadow .two-col table.table-headings tr .tab-class {width: 400px;} +.no-textshadow .two-col table.table-headings tr .model-1 { } +.no-textshadow .two-col table.table-headings tr .model-2 { padding-right: 30px; } +.specifications-set table tr th.over-hang { width: 15px; } +.specifications-set table.table-headings { width: 766px;} + +.specifications-set table tr th.tab-class {font-weight: bold; text-align: left;} +.specifications-set table tr td {margin: 1px; padding:5px 10px 5px 10px; color: #717171; } +.specifications-set table tr .stat {width: 130px; text-align: center;} + + +.specifications-set.fwd ul.table-tabs li a { } +.specifications-set.fwd ul.table-tabs li.current a { color: #fff; } + diff --git a/public/img/glyphicons-halflings-white.png b/public/img/glyphicons-halflings-white.png new file mode 100644 index 0000000..3bf6484 Binary files /dev/null and b/public/img/glyphicons-halflings-white.png differ diff --git a/public/img/glyphicons-halflings.png b/public/img/glyphicons-halflings.png new file mode 100644 index 0000000..a996999 Binary files /dev/null and b/public/img/glyphicons-halflings.png differ diff --git a/public/js/bootstrap.js b/public/js/bootstrap.js new file mode 100644 index 0000000..a81171b --- /dev/null +++ b/public/js/bootstrap.js @@ -0,0 +1,2268 @@ +/* =================================================== + * bootstrap-transition.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ + + $(function () { + + $.support.transition = (function () { + + var transitionEnd = (function () { + + var el = document.createElement('bootstrap') + , transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd' + , 'MozTransition' : 'transitionend' + , 'OTransition' : 'oTransitionEnd otransitionend' + , 'transition' : 'transitionend' + } + , name + + for (name in transEndEventNames){ + if (el.style[name] !== undefined) { + return transEndEventNames[name] + } + } + + }()) + + return transitionEnd && { + end: transitionEnd + } + + })() + + }) + +}(window.jQuery);/* ========================================================== + * bootstrap-alert.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent.trigger(e = $.Event('close')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT NO CONFLICT + * ================= */ + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + /* ALERT DATA-API + * ============== */ + + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) + +}(window.jQuery);/* ============================================================ + * bootstrap-button.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON NO CONFLICT + * ================== */ + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + /* BUTTON DATA-API + * =============== */ + + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + +}(window.jQuery);/* ========================================================== + * bootstrap-carousel.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.prototype = { + + cycle: function (e) { + if (!e) this.paused = false + if (this.interval) clearInterval(this.interval); + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + } + + , getActiveIndex: function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + return this.$items.index(this.$active) + } + + , to: function (pos) { + var activeIndex = this.getActiveIndex() + , that = this + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activeIndex == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + , pause: function (e) { + if (!e) this.paused = true + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle() + } + clearInterval(this.interval) + this.interval = null + return this + } + + , next: function () { + if (this.sliding) return + return this.slide('next') + } + + , prev: function () { + if (this.sliding) return + return this.slide('prev') + } + + , slide: function (type, next) { + var $active = this.$element.find('.item.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + , e + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + e = $.Event('slide', { + relatedTarget: $next[0] + , direction: direction + }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) + , action = typeof option == 'string' ? option : options.slide + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000 + , pause: 'hover' + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL NO CONFLICT + * ==================== */ + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + /* CAROUSEL DATA-API + * ================= */ + + $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + , slideIndex + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('carousel').pause().to(slideIndex).cycle() + } + + e.preventDefault() + }) + +}(window.jQuery);/* ============================================================= + * bootstrap-collapse.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* COLLAPSE PUBLIC CLASS DEFINITION + * ================================ */ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options.parent) { + this.$parent = $(this.options.parent) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse + + , dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + , show: function () { + var dimension + , scroll + , actives + , hasData + + if (this.transitioning || this.$element.hasClass('in')) return + + dimension = this.dimension() + scroll = $.camelCase(['scroll', dimension].join('-')) + actives = this.$parent && this.$parent.find('> .accordion-group > .in') + + if (actives && actives.length) { + hasData = actives.data('collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', $.Event('show'), 'shown') + $.support.transition && this.$element[dimension](this.$element[0][scroll]) + } + + , hide: function () { + var dimension + if (this.transitioning || !this.$element.hasClass('in')) return + dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', $.Event('hide'), 'hidden') + this.$element[dimension](0) + } + + , reset: function (size) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') + + return this + } + + , transition: function (method, startEvent, completeEvent) { + var that = this + , complete = function () { + if (startEvent.type == 'show') that.reset() + that.transitioning = 0 + that.$element.trigger(completeEvent) + } + + this.$element.trigger(startEvent) + + if (startEvent.isDefaultPrevented()) return + + this.transitioning = 1 + + this.$element[method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + } + + , toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* COLLAPSE PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSE NO CONFLICT + * ==================== */ + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + /* COLLAPSE DATA-API + * ================= */ + + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) + }) + +}(window.jQuery);/* ============================================================ + * bootstrap-dropdown.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + $parent.toggleClass('open') + } + + $this.focus() + + return false + } + + , keydown: function (e) { + var $this + , $items + , $active + , $parent + , isActive + , index + + if (!/(38|40|27)/.test(e.keyCode)) return + + $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + if (!isActive || (isActive && e.keyCode == 27)) { + if (e.which == 27) $parent.find(toggle).focus() + return $this.click() + } + + $items = $('[role=menu] li:not(.divider):visible a', $parent) + + if (!$items.length) return + + index = $items.index($items.filter(':focus')) + + if (e.keyCode == 38 && index > 0) index-- // up + if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items + .eq(index) + .focus() + } + + } + + function clearMenus() { + $(toggle).each(function () { + getParent($(this)).removeClass('open') + }) + } + + function getParent($this) { + var selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = selector && $(selector) + + if (!$parent || !$parent.length) $parent = $this.parent() + + return $parent + } + + + /* DROPDOWN PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.dropdown + + $.fn.dropdown = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('dropdown') + if (!data) $this.data('dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.dropdown.Constructor = Dropdown + + + /* DROPDOWN NO CONFLICT + * ==================== */ + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + /* APPLY TO STANDARD DROPDOWN ELEMENTS + * =================================== */ + + $(document) + .on('click.dropdown.data-api', clearMenus) + .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('.dropdown-menu', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) + +}(window.jQuery); +/* ========================================================= + * bootstrap-modal.js v2.3.0 + * http://twitter.github.com/bootstrap/javascript.html#modals + * ========================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* MODAL CLASS DEFINITION + * ====================== */ + + var Modal = function (element, options) { + this.options = options + this.$element = $(element) + .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) + this.options.remote && this.$element.find('.modal-body').load(this.options.remote) + } + + Modal.prototype = { + + constructor: Modal + + , toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + , e = $.Event('show') + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.escape() + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(document.body) //don't move modals dom position + } + + that.$element.show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element + .addClass('in') + .attr('aria-hidden', false) + + that.enforceFocus() + + transition ? + that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) : + that.$element.focus().trigger('shown') + + }) + } + + , hide: function (e) { + e && e.preventDefault() + + var that = this + + e = $.Event('hide') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + + $(document).off('focusin.modal') + + this.$element + .removeClass('in') + .attr('aria-hidden', true) + + $.support.transition && this.$element.hasClass('fade') ? + this.hideWithTransition() : + this.hideModal() + } + + , enforceFocus: function () { + var that = this + $(document).on('focusin.modal', function (e) { + if (that.$element[0] !== e.target && !that.$element.has(e.target).length) { + that.$element.focus() + } + }) + } + + , escape: function () { + var that = this + if (this.isShown && this.options.keyboard) { + this.$element.on('keyup.dismiss.modal', function ( e ) { + e.which == 27 && that.hide() + }) + } else if (!this.isShown) { + this.$element.off('keyup.dismiss.modal') + } + } + + , hideWithTransition: function () { + var that = this + , timeout = setTimeout(function () { + that.$element.off($.support.transition.end) + that.hideModal() + }, 500) + + this.$element.one($.support.transition.end, function () { + clearTimeout(timeout) + that.hideModal() + }) + } + + , hideModal: function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.removeBackdrop() + that.$element.trigger('hidden') + }) + } + + , removeBackdrop: function () { + this.$backdrop.remove() + this.$backdrop = null + } + + , backdrop: function (callback) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('