This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

4
vendor/alchemy/mediavorus/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/nbproject
/vendor
/docs/_build
composer.phar

19
vendor/alchemy/mediavorus/.travis.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
language: php
sudo: required
before_install:
- composer self-update --rollback
- sudo apt-get update
- sudo apt-get install ffmpeg
- phpenv config-rm xdebug.ini
install:
- composer update --prefer-source
php:
- 5.6
- 7.0
- 7.1
matrix:
fast_finish: true

60
vendor/alchemy/mediavorus/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,60 @@
CHANGELOG
---------
* 0.4.4 (08-26-2014)
* Fix width and height video extraction (@nlegoff).
* 0.4.3 (01-06-2014)
* Fix video audio sample rate cast.
* 0.4.2 (11-28-2013)
* Add support for video orientation.
* 0.4.1 (10-21-2013)
* Add compatibility with PHP-FFMpeg 0.4.
* Fix temporary files management.
* 0.4.0 (07-04-2013)
* Add compatibility with PHP-FFMpeg 0.3.
* BC Break : Implementation must now explicitely registered MediaVorus
mimetype guessers as they are not automatically registered anymore.
* Ensure FFProbe dependency is optional.
* 0.3.2 (04-16-2013)
* Cleanup JMS Serializer / exiftool / PHPExiftool version dependencies
* 0.3.1 (01-31-2013)
* Merge with 0.1.2
* Register FileBinaryMimeTypeGuesser prior to FileInfoMimetypeGuesser
* 0.3.0 (01-14-2013)
* Add support for media serialization via JMS serializer.
* 0.2.1 (12-21-2012)
* Support of the latest PHPExiftool API.
* 0.2.0 (12-14-2012)
* Update API.
* Add support of videos Width/Height via FFProbe.
* 0.1.2 (02-07-2013)
* Add more mime types to match the document format.
* 0.1.1 (12-14-2012)
* Support for Video Width / Height extraction via FFProbe.
* 0.1.0 (11-26-2012)
* First stable version.

18
vendor/alchemy/mediavorus/LICENSE vendored Normal file
View File

@@ -0,0 +1,18 @@
This project is released under MIT License
Copyright (c) 2012 Romain Neutron
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 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.

27
vendor/alchemy/mediavorus/README.md vendored Normal file
View File

@@ -0,0 +1,27 @@
MediaVorus
==========
[![Build Status](https://secure.travis-ci.org/romainneutron/MediaVorus.png?branch=master)](http://travis-ci.org/romainneutron/MediaVorus)
A lib to get every technical informations about your files
#Exemple
```php
use MediaVorus\MediaVorus;
use MediaVorus\Media\Image;
$mediavorus = MediaVorus::create();
$image = $mediavorus->guess('RawCanon.cr2');
echo sprintf("Photo as been taken with a %s Shutter Speed", $Image->getShutterSpeed());
```
#Documentation
Documentation is hosted on Read The Docs http://mediavorus.readthedocs.org/
#License
MediaVorus is released under the [MIT license](http://opensource.org/licenses/MIT)

45
vendor/alchemy/mediavorus/composer.json vendored Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "alchemy/mediavorus",
"type": "library",
"description": "MediaVorus",
"keywords": ["metadata"],
"license": "MIT",
"authors": [
{
"name": "Romain Neutron",
"email": "imprec@gmail.com",
"homepage": "http://www.lickmychip.com/"
}
],
"require": {
"php": ">=5.3.0",
"alchemy/phpexiftool" : "~0.1",
"doctrine/collections" : "~1.0",
"symfony/http-foundation" : "~2.0",
"php-ffmpeg/php-ffmpeg" : "~0.3",
"monolog/monolog" : "~1.0"
},
"suggest": {
"jms/serializer" : "To serialize Medias",
"symfony/yaml" : "To serialize Medias in Yaml format"
},
"require-dev": {
"silex/silex" : "~1.0",
"symfony/yaml" : "~2.0",
"jms/serializer" : "~0.12.0",
"phpunit/phpunit" : "^4.0|^5.0"
},
"replace": {
"mediavorus/mediavorus": "<=0.4.4"
},
"autoload": {
"psr-0": {
"MediaVorus": "src"
}
},
"extra": {
"branch-alias": {
"dev-master": "0.4.x-dev"
}
}
}

1932
vendor/alchemy/mediavorus/composer.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
API
===
.. toctree::
:maxdepth: 2

153
vendor/alchemy/mediavorus/docs/Makefile vendored Normal file
View File

@@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MediaVorus.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MediaVorus.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/MediaVorus"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MediaVorus"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

View File

@@ -0,0 +1,7 @@
Use Cases
=========
.. toctree::
:maxdepth: 2

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function f(){ log.history = log.history || []; log.history.push(arguments); if(this.console) { var args = arguments, newarr; try { args.callee = f.caller } catch(e) {}; newarr = [].slice.call(args); if (typeof console.log === 'object') log.apply.call(console.log, console, newarr); else console.log.apply(console, newarr);}};
// make it safe to use console.log always
(function(a){function b(){}for(var c="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),d;!!(d=c.pop());){a[d]=a[d]||b;}})
(function(){try{console.log();return window.console;}catch(a){return (window.console={});}}());
// place any jQuery/helper plugins in here, instead of separate, slower script files.

View File

@@ -0,0 +1,8 @@
/* Author:
*/

View File

@@ -0,0 +1,28 @@
// ACCORDION
// ---------
// Parent container
.accordion {
margin-bottom: @baseLineHeight;
}
// Group == heading + body
.accordion-group {
margin-bottom: 2px;
border: 1px solid #e5e5e5;
.border-radius(4px);
}
.accordion-heading {
border-bottom: 0;
}
.accordion-heading .accordion-toggle {
display: block;
padding: 8px 15px;
}
// Inner needs the styles because you can't animate properly with any styles on the element
.accordion-inner {
padding: 9px 15px;
border-top: 1px solid #e5e5e5;
}

View File

@@ -0,0 +1,58 @@
// ALERT STYLES
// ------------
// Base alert styles
.alert {
padding: 8px 35px 8px 14px;
margin-bottom: @baseLineHeight;
text-shadow: 0 1px 0 rgba(255,255,255,.5);
background-color: @warningBackground;
border: 1px solid @warningBorder;
.border-radius(4px);
color: @warningText;
}
.alert-heading {
color: inherit;
}
// Adjust close link position
.alert .close {
position: relative;
top: -2px;
right: -21px;
line-height: 18px;
}
// Alternate styles
// ----------------
.alert-success {
background-color: @successBackground;
border-color: @successBorder;
color: @successText;
}
.alert-danger,
.alert-error {
background-color: @errorBackground;
border-color: @errorBorder;
color: @errorText;
}
.alert-info {
background-color: @infoBackground;
border-color: @infoBorder;
color: @infoText;
}
// Block alerts
// ------------------------
.alert-block {
padding-top: 14px;
padding-bottom: 14px;
}
.alert-block > p,
.alert-block > ul {
margin-bottom: 0;
}
.alert-block p + p {
margin-top: 5px;
}

View File

@@ -0,0 +1,36 @@
// BADGES
// ------
// Base
.badge {
padding: 1px 9px 2px;
font-size: @baseFontSize * .925;
font-weight: bold;
white-space: nowrap;
color: @white;
background-color: @grayLight;
.border-radius(9px);
}
// Hover state
.badge:hover {
color: @white;
text-decoration: none;
cursor: pointer;
}
// Colors
.badge-error { background-color: @errorText; }
.badge-error:hover { background-color: darken(@errorText, 10%); }
.badge-warning { background-color: @orange; }
.badge-warning:hover { background-color: darken(@orange, 10%); }
.badge-success { background-color: @successText; }
.badge-success:hover { background-color: darken(@successText, 10%); }
.badge-info { background-color: @infoText; }
.badge-info:hover { background-color: darken(@infoText, 10%); }
.badge-inverse { background-color: @grayDark; }
.badge-inverse:hover { background-color: darken(@grayDark, 10%); }

View File

@@ -0,0 +1,63 @@
/*!
* Bootstrap v2.0.2
*
* 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.
*/
// CSS Reset
@import "reset.less";
// Core variables and mixins
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
@import "mixins.less";
// Grid system and page structure
@import "scaffolding.less";
@import "grid.less";
@import "layouts.less";
// Base CSS
@import "type.less";
@import "code.less";
@import "forms.less";
@import "tables.less";
// Components: common
@import "sprites.less";
@import "dropdowns.less";
@import "wells.less";
@import "component-animations.less";
@import "close.less";
// Components: Buttons & Alerts
@import "buttons.less";
@import "button-groups.less";
@import "alerts.less"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less
// Components: Nav
@import "navs.less";
@import "navbar.less";
@import "breadcrumbs.less";
@import "pagination.less";
@import "pager.less";
// Components: Popovers
@import "modals.less";
@import "tooltip.less";
@import "popovers.less";
// Components: Misc
@import "thumbnails.less";
@import "labels.less";
@import "badges.less";
@import "progress-bars.less";
@import "accordion.less";
@import "carousel.less";
@import "hero-unit.less";
// Utility classes
@import "utilities.less"; // Has to be last to override when necessary

View File

@@ -0,0 +1,24 @@
// BREADCRUMBS
// -----------
.breadcrumb {
padding: 7px 14px;
margin: 0 0 @baseLineHeight;
list-style: none;
#gradient > .vertical(@white, #f5f5f5);
border: 1px solid #ddd;
.border-radius(3px);
.box-shadow(inset 0 1px 0 @white);
li {
display: inline-block;
.ie7-inline-block();
text-shadow: 0 1px 0 @white;
}
.divider {
padding: 0 5px;
color: @grayLight;
}
.active a {
color: @grayDark;
}
}

View File

@@ -0,0 +1,172 @@
// BUTTON GROUPS
// -------------
// Make the div behave like a button
.btn-group {
position: relative;
.clearfix(); // clears the floated buttons
.ie7-restore-left-whitespace();
}
// Space out series of button groups
.btn-group + .btn-group {
margin-left: 5px;
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
margin-top: @baseLineHeight / 2;
margin-bottom: @baseLineHeight / 2;
.btn-group {
display: inline-block;
.ie7-inline-block();
}
}
// Float them, remove border radius, then re-add to first and last elements
.btn-group .btn {
position: relative;
float: left;
margin-left: -1px;
.border-radius(0);
}
// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
.btn-group .btn:first-child {
margin-left: 0;
-webkit-border-top-left-radius: 4px;
-moz-border-radius-topleft: 4px;
border-top-left-radius: 4px;
-webkit-border-bottom-left-radius: 4px;
-moz-border-radius-bottomleft: 4px;
border-bottom-left-radius: 4px;
}
.btn-group .btn:last-child,
.btn-group .dropdown-toggle {
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topright: 4px;
border-top-right-radius: 4px;
-webkit-border-bottom-right-radius: 4px;
-moz-border-radius-bottomright: 4px;
border-bottom-right-radius: 4px;
}
// Reset corners for large buttons
.btn-group .btn.large:first-child {
margin-left: 0;
-webkit-border-top-left-radius: 6px;
-moz-border-radius-topleft: 6px;
border-top-left-radius: 6px;
-webkit-border-bottom-left-radius: 6px;
-moz-border-radius-bottomleft: 6px;
border-bottom-left-radius: 6px;
}
.btn-group .btn.large:last-child,
.btn-group .large.dropdown-toggle {
-webkit-border-top-right-radius: 6px;
-moz-border-radius-topright: 6px;
border-top-right-radius: 6px;
-webkit-border-bottom-right-radius: 6px;
-moz-border-radius-bottomright: 6px;
border-bottom-right-radius: 6px;
}
// On hover/focus/active, bring the proper btn to front
.btn-group .btn:hover,
.btn-group .btn:focus,
.btn-group .btn:active,
.btn-group .btn.active {
z-index: 2;
}
// On active and open, don't show outline
.btn-group .dropdown-toggle:active,
.btn-group.open .dropdown-toggle {
outline: 0;
}
// Split button dropdowns
// ----------------------
// Give the line between buttons some depth
.btn-group .dropdown-toggle {
padding-left: 8px;
padding-right: 8px;
@shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
.box-shadow(@shadow);
*padding-top: 3px;
*padding-bottom: 3px;
}
.btn-group .btn-mini.dropdown-toggle {
padding-left: 5px;
padding-right: 5px;
*padding-top: 1px;
*padding-bottom: 1px;
}
.btn-group .btn-small.dropdown-toggle {
*padding-top: 4px;
*padding-bottom: 4px;
}
.btn-group .btn-large.dropdown-toggle {
padding-left: 12px;
padding-right: 12px;
}
.btn-group.open {
// IE7's z-index only goes to the nearest positioned ancestor, which would
// make the menu appear below buttons that appeared later on the page
*z-index: @zindexDropdown;
// Reposition menu on open and round all corners
.dropdown-menu {
display: block;
margin-top: 1px;
.border-radius(5px);
}
.dropdown-toggle {
background-image: none;
@shadow: inset 0 1px 6px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
.box-shadow(@shadow);
}
}
// Reposition the caret
.btn .caret {
margin-top: 7px;
margin-left: 0;
}
.btn:hover .caret,
.open.btn-group .caret {
.opacity(100);
}
// Carets in other button sizes
.btn-mini .caret {
margin-top: 5px;
}
.btn-small .caret {
margin-top: 6px;
}
.btn-large .caret {
margin-top: 6px;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid @black;
}
// Account for other colors
.btn-primary,
.btn-warning,
.btn-danger,
.btn-info,
.btn-success,
.btn-inverse {
.caret {
border-top-color: @white;
border-bottom-color: @white;
.opacity(75);
}
}

View File

@@ -0,0 +1,187 @@
// BUTTON STYLES
// -------------
// Base styles
// --------------------------------------------------
// Core
.btn {
display: inline-block;
.ie7-inline-block();
padding: 4px 10px 4px;
margin-bottom: 0; // For input.btn
font-size: @baseFontSize;
line-height: @baseLineHeight;
color: @grayDark;
text-align: center;
text-shadow: 0 1px 1px rgba(255,255,255,.75);
vertical-align: middle;
.buttonBackground(@btnBackground, @btnBackgroundHighlight);
border: 1px solid @btnBorder;
border-bottom-color: darken(@btnBorder, 10%);
.border-radius(4px);
@shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
.box-shadow(@shadow);
cursor: pointer;
// Give IE7 some love
.ie7-restore-left-whitespace();
}
// Hover state
.btn:hover {
color: @grayDark;
text-decoration: none;
background-color: darken(@white, 10%);
background-position: 0 -15px;
// transition is only when going to hover, otherwise the background
// behind the gradient (there for IE<=9 fallback) gets mismatched
.transition(background-position .1s linear);
}
// Focus state for keyboard and accessibility
.btn:focus {
.tab-focus();
}
// Active state
.btn.active,
.btn:active {
background-image: none;
@shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
.box-shadow(@shadow);
background-color: darken(@white, 10%);
background-color: darken(@white, 15%) e("\9");
outline: 0;
}
// Disabled state
.btn.disabled,
.btn[disabled] {
cursor: default;
background-image: none;
background-color: darken(@white, 10%);
.opacity(65);
.box-shadow(none);
}
// Button Sizes
// --------------------------------------------------
// Large
.btn-large {
padding: 9px 14px;
font-size: @baseFontSize + 2px;
line-height: normal;
.border-radius(5px);
}
.btn-large [class^="icon-"] {
margin-top: 1px;
}
// Small
.btn-small {
padding: 5px 9px;
font-size: @baseFontSize - 2px;
line-height: @baseLineHeight - 2px;
}
.btn-small [class^="icon-"] {
margin-top: -1px;
}
// Mini
.btn-mini {
padding: 2px 6px;
font-size: @baseFontSize - 2px;
line-height: @baseLineHeight - 4px;
}
// Alternate buttons
// --------------------------------------------------
// Set text color
// -------------------------
.btn-primary,
.btn-primary:hover,
.btn-warning,
.btn-warning:hover,
.btn-danger,
.btn-danger:hover,
.btn-success,
.btn-success:hover,
.btn-info,
.btn-info:hover,
.btn-inverse,
.btn-inverse:hover {
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
color: @white;
}
// Provide *some* extra contrast for those who can get it
.btn-primary.active,
.btn-warning.active,
.btn-danger.active,
.btn-success.active,
.btn-info.active,
.btn-inverse.active {
color: rgba(255,255,255,.75);
}
// Set the backgrounds
// -------------------------
.btn-primary {
.buttonBackground(@btnPrimaryBackground, @btnPrimaryBackgroundHighlight);
}
// Warning appears are orange
.btn-warning {
.buttonBackground(@btnWarningBackground, @btnWarningBackgroundHighlight);
}
// Danger and error appear as red
.btn-danger {
.buttonBackground(@btnDangerBackground, @btnDangerBackgroundHighlight);
}
// Success appears as green
.btn-success {
.buttonBackground(@btnSuccessBackground, @btnSuccessBackgroundHighlight);
}
// Info appears as a neutral blue
.btn-info {
.buttonBackground(@btnInfoBackground, @btnInfoBackgroundHighlight);
}
// Inverse appears as dark gray
.btn-inverse {
.buttonBackground(@btnInverseBackground, @btnInverseBackgroundHighlight);
}
// Cross-browser Jank
// --------------------------------------------------
button.btn,
input[type="submit"].btn {
// Firefox 3.6 only I believe
&::-moz-focus-inner {
padding: 0;
border: 0;
}
// IE7 has some default padding on button controls
*padding-top: 2px;
*padding-bottom: 2px;
&.btn-large {
*padding-top: 7px;
*padding-bottom: 7px;
}
&.btn-small {
*padding-top: 3px;
*padding-bottom: 3px;
}
&.btn-mini {
*padding-top: 1px;
*padding-bottom: 1px;
}
}

View File

@@ -0,0 +1,121 @@
// CAROUSEL
// --------
.carousel {
position: relative;
margin-bottom: @baseLineHeight;
line-height: 1;
}
.carousel-inner {
overflow: hidden;
width: 100%;
position: relative;
}
.carousel {
.item {
display: none;
position: relative;
.transition(.6s ease-in-out left);
}
// Account for jankitude on images
.item > img {
display: block;
line-height: 1;
}
.active,
.next,
.prev { display: block; }
.active {
left: 0;
}
.next,
.prev {
position: absolute;
top: 0;
width: 100%;
}
.next {
left: 100%;
}
.prev {
left: -100%;
}
.next.left,
.prev.right {
left: 0;
}
.active.left {
left: -100%;
}
.active.right {
left: 100%;
}
}
// Left/right controls for nav
// ---------------------------
.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: @white;
text-align: center;
background: @grayDarker;
border: 3px solid @white;
.border-radius(23px);
.opacity(50);
// we can't have this transition here
// because webkit cancels the carousel
// animation if you trip this while
// in the middle of another animation
// ;_;
// .transition(opacity .2s linear);
// Reposition the right one
&.right {
left: auto;
right: 15px;
}
// Hover state
&:hover {
color: @white;
text-decoration: none;
.opacity(90);
}
}
// Caption for text below images
// -----------------------------
.carousel-caption {
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 10px 15px 5px;
background: @grayDark;
background: rgba(0,0,0,.75);
}
.carousel-caption h4,
.carousel-caption p {
color: @white;
}

View File

@@ -0,0 +1,18 @@
// CLOSE ICONS
// -----------
.close {
float: right;
font-size: 20px;
font-weight: bold;
line-height: @baseLineHeight;
color: @black;
text-shadow: 0 1px 0 rgba(255,255,255,1);
.opacity(20);
&:hover {
color: @black;
text-decoration: none;
.opacity(40);
cursor: pointer;
}
}

View File

@@ -0,0 +1,57 @@
// Code.less
// Code typography styles for the <code> and <pre> elements
// --------------------------------------------------------
// Inline and block code styles
code,
pre {
padding: 0 3px 2px;
#font > #family > .monospace;
font-size: @baseFontSize - 1;
color: @grayDark;
.border-radius(3px);
}
// Inline code
code {
padding: 2px 4px;
color: #d14;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
}
// Blocks of code
pre {
display: block;
padding: (@baseLineHeight - 1) / 2;
margin: 0 0 @baseLineHeight / 2;
font-size: @baseFontSize * .925; // 13px to 12px
line-height: @baseLineHeight;
background-color: #f5f5f5;
border: 1px solid #ccc; // fallback for IE7-8
border: 1px solid rgba(0,0,0,.15);
.border-radius(4px);
white-space: pre;
white-space: pre-wrap;
word-break: break-all;
word-wrap: break-word;
// Make prettyprint styles more spaced out for readability
&.prettyprint {
margin-bottom: @baseLineHeight;
}
// Account for some code outputs that place code tags in pre tags
code {
padding: 0;
color: inherit;
background-color: transparent;
border: 0;
}
}
// Enable scrollable blocks of code
.pre-scrollable {
max-height: 340px;
overflow-y: scroll;
}

View File

@@ -0,0 +1,20 @@
// COMPONENT ANIMATIONS
// --------------------
.fade {
.transition(opacity .15s linear);
opacity: 0;
&.in {
opacity: 1;
}
}
.collapse {
.transition(height .35s ease);
position:relative;
overflow:hidden;
height: 0;
&.in {
height: auto;
}
}

View File

@@ -0,0 +1,148 @@
// DROPDOWN MENUS
// --------------
// Use the .menu class on any <li> element within the topbar or ul.tabs and you'll get some superfancy dropdowns
.dropdown {
position: relative;
}
.dropdown-toggle {
// The caret makes the toggle a bit too tall in IE7
*margin-bottom: -3px;
}
.dropdown-toggle:active,
.open .dropdown-toggle {
outline: 0;
}
// Dropdown arrow/caret
// --------------------
.caret {
display: inline-block;
width: 0;
height: 0;
vertical-align: top;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid @black;
.opacity(30);
content: "";
}
// Place the caret
.dropdown .caret {
margin-top: 8px;
margin-left: 2px;
}
.dropdown:hover .caret,
.open.dropdown .caret {
.opacity(100);
}
// The dropdown menu (ul)
// ----------------------
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: @zindexDropdown;
float: left;
display: none; // none by default, but block on "open" of the menu
min-width: 160px;
padding: 4px 0;
margin: 0; // override default ul
list-style: none;
background-color: @dropdownBackground;
border-color: #ccc;
border-color: rgba(0,0,0,.2);
border-style: solid;
border-width: 1px;
.border-radius(0 0 5px 5px);
.box-shadow(0 5px 10px rgba(0,0,0,.2));
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
*border-right-width: 2px;
*border-bottom-width: 2px;
// Aligns the dropdown menu to right
&.pull-right {
right: 0;
left: auto;
}
// Dividers (basically an hr) within the dropdown
.divider {
.nav-divider();
}
// Links within the dropdown menu
a {
display: block;
padding: 3px 15px;
clear: both;
font-weight: normal;
line-height: @baseLineHeight;
color: @dropdownLinkColor;
white-space: nowrap;
}
}
// Hover state
// -----------
.dropdown-menu li > a:hover,
.dropdown-menu .active > a,
.dropdown-menu .active > a:hover {
color: @dropdownLinkColorHover;
text-decoration: none;
background-color: @dropdownLinkBackgroundHover;
}
// Open state for the dropdown
// ---------------------------
.dropdown.open {
// IE7's z-index only goes to the nearest positioned ancestor, which would
// make the menu appear below buttons that appeared later on the page
*z-index: @zindexDropdown;
.dropdown-toggle {
color: @white;
background: #ccc;
background: rgba(0,0,0,.3);
}
.dropdown-menu {
display: block;
}
}
// Right aligned dropdowns
.pull-right .dropdown-menu {
left: auto;
right: 0;
}
// Allow for dropdowns to go bottom up (aka, dropup-menu)
// ------------------------------------------------------
// Just add .dropup after the standard .dropdown class and you're set, bro.
// TODO: abstract this so that the navbar fixed styles are not placed here?
.dropup,
.navbar-fixed-bottom .dropdown {
// Reverse the caret
.caret {
border-top: 0;
border-bottom: 4px solid @black;
content: "\2191";
}
// Different positioning for bottom up menu
.dropdown-menu {
top: auto;
bottom: 100%;
margin-bottom: 1px;
}
}
// Typeahead
// ---------
.typeahead {
margin-top: 2px; // give it some space to breathe
.border-radius(4px);
}

View File

@@ -0,0 +1,555 @@
// Forms.less
// Base styles for various input types, form layouts, and states
// -------------------------------------------------------------
// GENERAL STYLES
// --------------
// Make all forms have space below them
form {
margin: 0 0 @baseLineHeight;
}
fieldset {
padding: 0;
margin: 0;
border: 0;
}
// Groups of fields with labels on top (legends)
legend {
display: block;
width: 100%;
padding: 0;
margin-bottom: @baseLineHeight * 1.5;
font-size: @baseFontSize * 1.5;
line-height: @baseLineHeight * 2;
color: @grayDark;
border: 0;
border-bottom: 1px solid #eee;
// Small
small {
font-size: @baseLineHeight * .75;
color: @grayLight;
}
}
// Set font for forms
label,
input,
button,
select,
textarea {
#font > .shorthand(@baseFontSize,normal,@baseLineHeight); // Set size, weight, line-height here
}
input,
button,
select,
textarea {
font-family: @baseFontFamily; // And only set font-family here for those that need it (note the missing label element)
}
// Identify controls by their labels
label {
display: block;
margin-bottom: 5px;
color: @grayDark;
}
// Inputs, Textareas, Selects
input,
textarea,
select,
.uneditable-input {
display: inline-block;
width: 210px;
height: @baseLineHeight;
padding: 4px;
margin-bottom: 9px;
font-size: @baseFontSize;
line-height: @baseLineHeight;
color: @gray;
border: 1px solid @inputBorder;
.border-radius(3px);
}
.uneditable-textarea {
width: auto;
height: auto;
}
// Inputs within a label
label input,
label textarea,
label select {
display: block;
}
// Mini reset for unique input types
input[type="image"],
input[type="checkbox"],
input[type="radio"] {
width: auto;
height: auto;
padding: 0;
margin: 3px 0;
*margin-top: 0; /* IE7 */
line-height: normal;
cursor: pointer;
.border-radius(0);
border: 0 \9; /* IE9 and down */
}
input[type="image"] {
border: 0;
}
// Reset the file input to browser defaults
input[type="file"] {
width: auto;
padding: initial;
line-height: initial;
border: initial;
background-color: @inputBackground;
background-color: initial;
.box-shadow(none);
}
// Help out input buttons
input[type="button"],
input[type="reset"],
input[type="submit"] {
width: auto;
height: auto;
}
// Set the height of select and file controls to match text inputs
select,
input[type="file"] {
height: 28px; /* 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: 28px;
}
// Reset line-height for IE
input[type="file"] {
line-height: 18px \9;
}
// Chrome on Linux and Mobile Safari need background-color
select {
width: 220px; // default input width + 10px of padding that doesn't get applied
background-color: @inputBackground;
}
// Make multiple select elements height not fixed
select[multiple],
select[size] {
height: auto;
}
// Remove shadow from image inputs
input[type="image"] {
.box-shadow(none);
}
// Make textarea height behave
textarea {
height: auto;
}
// Hidden inputs
input[type="hidden"] {
display: none;
}
// CHECKBOXES & RADIOS
// -------------------
// Indent the labels to position radios/checkboxes as hanging
.radio,
.checkbox {
padding-left: 18px;
}
.radio input[type="radio"],
.checkbox input[type="checkbox"] {
float: left;
margin-left: -18px;
}
// Move the options list down to align with labels
.controls > .radio:first-child,
.controls > .checkbox:first-child {
padding-top: 5px; // has to be padding because margin collaspes
}
// Radios and checkboxes on same line
// TODO v3: Convert .inline to .control-inline
.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; // space out consecutive inline controls
}
// FOCUS STATE
// -----------
input,
textarea {
.box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
@transition: border linear .2s, box-shadow linear .2s;
.transition(@transition);
}
input:focus,
textarea:focus {
border-color: rgba(82,168,236,.8);
@shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
.box-shadow(@shadow);
outline: 0;
outline: thin dotted \9; /* IE6-9 */
}
input[type="file"]:focus,
input[type="radio"]:focus,
input[type="checkbox"]:focus,
select:focus {
.box-shadow(none); // override for file inputs
.tab-focus();
}
// INPUT SIZES
// -----------
// General classes for quick sizes
.input-mini { width: 60px; }
.input-small { width: 90px; }
.input-medium { width: 150px; }
.input-large { width: 210px; }
.input-xlarge { width: 270px; }
.input-xxlarge { width: 530px; }
// Grid style input sizes
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
float: none;
margin-left: 0;
}
// GRID SIZING FOR INPUTS
// ----------------------
#grid > .input (@gridColumnWidth, @gridGutterWidth);
// DISABLED STATE
// --------------
// Disabled and read-only inputs
input[disabled],
select[disabled],
textarea[disabled],
input[readonly],
select[readonly],
textarea[readonly] {
background-color: @inputDisabledBackground;
border-color: #ddd;
cursor: not-allowed;
}
// FORM FIELD FEEDBACK STATES
// --------------------------
// Warning
.control-group.warning {
.formFieldState(@warningText, @warningText, @warningBackground);
}
// Error
.control-group.error {
.formFieldState(@errorText, @errorText, @errorBackground);
}
// Success
.control-group.success {
.formFieldState(@successText, @successText, @successBackground);
}
// HTML5 invalid states
// Shares styles with the .control-group.error above
input:focus:required:invalid,
textarea:focus:required:invalid,
select:focus:required:invalid {
color: #b94a48;
border-color: #ee5f5b;
&:focus {
border-color: darken(#ee5f5b, 10%);
.box-shadow(0 0 6px lighten(#ee5f5b, 20%));
}
}
// FORM ACTIONS
// ------------
.form-actions {
padding: (@baseLineHeight - 1) 20px @baseLineHeight;
margin-top: @baseLineHeight;
margin-bottom: @baseLineHeight;
background-color: @grayLighter;
border-top: 1px solid #ddd;
.clearfix(); // Adding clearfix to allow for .pull-right button containers
}
// For text that needs to appear as an input but should not be an input
.uneditable-input {
display: block;
background-color: @inputBackground;
border-color: #eee;
.box-shadow(inset 0 1px 2px rgba(0,0,0,.025));
cursor: not-allowed;
}
// Placeholder text gets special styles; can't be bundled together though for some reason
.placeholder(@grayLight);
// HELP TEXT
// ---------
.help-block,
.help-inline {
color: @gray; // lighten the text some for contrast
}
.help-block {
display: block; // account for any element using help-block
margin-bottom: @baseLineHeight / 2;
}
.help-inline {
display: inline-block;
.ie7-inline-block();
vertical-align: middle;
padding-left: 5px;
}
// INPUT GROUPS
// ------------
// Allow us to put symbols and text within the input field for a cleaner look
.input-prepend,
.input-append {
margin-bottom: 5px;
input,
select,
.uneditable-input {
*margin-left: 0;
.border-radius(0 3px 3px 0);
&:focus {
position: relative;
z-index: 2;
}
}
.uneditable-input {
border-left-color: #ccc;
}
.add-on {
display: inline-block;
width: auto;
min-width: 16px;
height: @baseLineHeight;
padding: 4px 5px;
font-weight: normal;
line-height: @baseLineHeight;
text-align: center;
text-shadow: 0 1px 0 @white;
vertical-align: middle;
background-color: @grayLighter;
border: 1px solid #ccc;
}
.add-on,
.btn {
.border-radius(3px 0 0 3px);
}
.active {
background-color: lighten(@green, 30);
border-color: @green;
}
}
.input-prepend {
.add-on,
.btn {
margin-right: -1px;
}
}
.input-append {
input,
select
.uneditable-input {
.border-radius(3px 0 0 3px);
}
.uneditable-input {
border-left-color: #eee;
border-right-color: #ccc;
}
.add-on,
.btn {
margin-left: -1px;
.border-radius(0 3px 3px 0);
}
}
// Remove all border-radius for inputs with both prepend and append
.input-prepend.input-append {
input,
select,
.uneditable-input {
.border-radius(0);
}
.add-on:first-child,
.btn:first-child {
margin-right: -1px;
.border-radius(3px 0 0 3px);
}
.add-on:last-child,
.btn:last-child {
margin-left: -1px;
.border-radius(0 3px 3px 0);
}
}
// SEARCH FORM
// -----------
.search-query {
padding-left: 14px;
padding-right: 14px;
margin-bottom: 0; // remove the default margin on all inputs
.border-radius(14px);
}
// HORIZONTAL & VERTICAL FORMS
// ---------------------------
// Common properties
// -----------------
.form-search,
.form-inline,
.form-horizontal {
input,
textarea,
select,
.help-inline,
.uneditable-input,
.input-prepend,
.input-append {
display: inline-block;
margin-bottom: 0;
}
// Re-hide hidden elements due to specifity
.hide {
display: none;
}
}
.form-search label,
.form-inline label {
display: inline-block;
}
// Remove margin for input-prepend/-append
.form-search .input-append,
.form-inline .input-append,
.form-search .input-prepend,
.form-inline .input-prepend {
margin-bottom: 0;
}
// Inline checkbox/radio labels (remove padding on left)
.form-search .radio,
.form-search .checkbox,
.form-inline .radio,
.form-inline .checkbox {
padding-left: 0;
margin-bottom: 0;
vertical-align: middle;
}
// Remove float and margin, set to inline-block
.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-left: 0;
margin-right: 3px;
}
// Margin to space out fieldsets
.control-group {
margin-bottom: @baseLineHeight / 2;
}
// Legend collapses margin, so next element is responsible for spacing
legend + .control-group {
margin-top: @baseLineHeight;
-webkit-margin-top-collapse: separate;
}
// Horizontal-specific styles
// --------------------------
.form-horizontal {
// Increase spacing between groups
.control-group {
margin-bottom: @baseLineHeight;
.clearfix();
}
// Float the labels left
.control-label {
float: left;
width: 140px;
padding-top: 5px;
text-align: right;
}
// Move over all input controls and content
.controls {
margin-left: 160px;
/* Super jank IE7 fix to ensure the inputs in .input-append and input-prepend don't inherit the margin of the parent, in this case .controls */
*display: inline-block;
*margin-left: 0;
*padding-left: 20px;
}
// Remove bottom margin on block level help text since that's accounted for on .control-group
.help-block {
margin-top: @baseLineHeight / 2;
margin-bottom: 0;
}
// Move over buttons in .form-actions to align with .controls
.form-actions {
padding-left: 160px;
}
}

View File

@@ -0,0 +1,5 @@
// Fixed (940px)
#grid > .core(@gridColumnWidth, @gridGutterWidth);
// Fluid (940px)
#grid > .fluid(@fluidGridColumnWidth, @fluidGridGutterWidth);

View File

@@ -0,0 +1,22 @@
// HERO UNIT
// ---------
.hero-unit {
padding: 60px;
margin-bottom: 30px;
background-color: @heroUnitBackground;
.border-radius(6px);
h1 {
margin-bottom: 0;
font-size: 60px;
line-height: 1;
color: @heroUnitHeadingColor;
letter-spacing: -1px;
}
p {
font-size: 18px;
font-weight: 200;
line-height: @baseLineHeight * 1.5;
color: @heroUnitLeadColor;
}
}

View File

@@ -0,0 +1,38 @@
// LABELS
// ------
// Base
.label {
padding: 1px 4px 2px;
font-size: @baseFontSize * .846;
font-weight: bold;
line-height: 13px; // ensure proper line-height if floated
color: @white;
vertical-align: middle;
white-space: nowrap;
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
background-color: @grayLight;
.border-radius(3px);
}
// Hover state
.label:hover {
color: @white;
text-decoration: none;
}
// Colors
.label-important { background-color: @errorText; }
.label-important:hover { background-color: darken(@errorText, 10%); }
.label-warning { background-color: @orange; }
.label-warning:hover { background-color: darken(@orange, 10%); }
.label-success { background-color: @successText; }
.label-success:hover { background-color: darken(@successText, 10%); }
.label-info { background-color: @infoText; }
.label-info:hover { background-color: darken(@infoText, 10%); }
.label-inverse { background-color: @grayDark; }
.label-inverse:hover { background-color: darken(@grayDark, 10%); }

View File

@@ -0,0 +1,17 @@
//
// Layouts
// Fixed-width and fluid (with sidebar) layouts
// --------------------------------------------
// Container (centered, fixed-width layouts)
.container {
.container-fixed();
}
// Fluid layouts (left aligned, with sidebar, min- & max-width content)
.container-fluid {
padding-left: @gridGutterWidth;
padding-right: @gridGutterWidth;
.clearfix();
}

View File

@@ -0,0 +1,614 @@
// Mixins.less
// Snippets of reusable CSS to develop faster and keep code readable
// -----------------------------------------------------------------
// UTILITY MIXINS
// --------------------------------------------------
// Clearfix
// --------
// For clearing floats like a boss h5bp.com/q
.clearfix {
*zoom: 1;
&:before,
&:after {
display: table;
content: "";
}
&:after {
clear: both;
}
}
// Webkit-style focus
// ------------------
.tab-focus() {
// Default
outline: thin dotted #333;
// Webkit
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
// Center-align a block level element
// ----------------------------------
.center-block() {
display: block;
margin-left: auto;
margin-right: auto;
}
// IE7 inline-block
// ----------------
.ie7-inline-block() {
*display: inline; /* IE7 inline-block hack */
*zoom: 1;
}
// IE7 likes to collapse whitespace on either side of the inline-block elements.
// Ems because we're attempting to match the width of a space character. Left
// version is for form buttons, which typically come after other elements, and
// right version is for icons, which come before. Applying both is ok, but it will
// mean that space between those elements will be .6em (~2 space characters) in IE7,
// instead of the 1 space in other browsers.
.ie7-restore-left-whitespace() {
*margin-left: .3em;
&:first-child {
*margin-left: 0;
}
}
.ie7-restore-right-whitespace() {
*margin-right: .3em;
&:last-child {
*margin-left: 0;
}
}
// Sizing shortcuts
// -------------------------
.size(@height: 5px, @width: 5px) {
width: @width;
height: @height;
}
.square(@size: 5px) {
.size(@size, @size);
}
// Placeholder text
// -------------------------
.placeholder(@color: @placeholderText) {
:-moz-placeholder {
color: @color;
}
::-webkit-input-placeholder {
color: @color;
}
}
// Text overflow
// -------------------------
// Requires inline-block or block for proper styling
.text-overflow() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// New image replacement
// -------------------------
// Source: http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/
.hide-text {
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
}
// FONTS
// --------------------------------------------------
#font {
#family {
.serif() {
font-family: Georgia, "Times New Roman", Times, serif;
}
.sans-serif() {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.monospace() {
font-family: Menlo, Monaco, "Courier New", monospace;
}
}
.shorthand(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
font-size: @size;
font-weight: @weight;
line-height: @lineHeight;
}
.serif(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
#font > #family > .serif;
#font > .shorthand(@size, @weight, @lineHeight);
}
.sans-serif(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
#font > #family > .sans-serif;
#font > .shorthand(@size, @weight, @lineHeight);
}
.monospace(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
#font > #family > .monospace;
#font > .shorthand(@size, @weight, @lineHeight);
}
}
// FORMS
// --------------------------------------------------
// Block level inputs
.input-block-level {
display: block;
width: 100%;
min-height: 28px; /* Make inputs at least the height of their button counterpart */
/* Makes inputs behave like true block-level elements */
.box-sizing(border-box);
}
// Mixin for form field states
.formFieldState(@textColor: #555, @borderColor: #ccc, @backgroundColor: #f5f5f5) {
// Set the text color
> label,
.help-block,
.help-inline {
color: @textColor;
}
// Style inputs accordingly
input,
select,
textarea {
color: @textColor;
border-color: @borderColor;
&:focus {
border-color: darken(@borderColor, 10%);
.box-shadow(0 0 6px lighten(@borderColor, 20%));
}
}
// Give a small background color for input-prepend/-append
.input-prepend .add-on,
.input-append .add-on {
color: @textColor;
background-color: @backgroundColor;
border-color: @textColor;
}
}
// CSS3 PROPERTIES
// --------------------------------------------------
// Border Radius
.border-radius(@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
// Drop shadows
.box-shadow(@shadow: 0 1px 3px rgba(0,0,0,.25)) {
-webkit-box-shadow: @shadow;
-moz-box-shadow: @shadow;
box-shadow: @shadow;
}
// Transitions
.transition(@transition) {
-webkit-transition: @transition;
-moz-transition: @transition;
-ms-transition: @transition;
-o-transition: @transition;
transition: @transition;
}
// Transformations
.rotate(@degrees) {
-webkit-transform: rotate(@degrees);
-moz-transform: rotate(@degrees);
-ms-transform: rotate(@degrees);
-o-transform: rotate(@degrees);
transform: rotate(@degrees);
}
.scale(@ratio) {
-webkit-transform: scale(@ratio);
-moz-transform: scale(@ratio);
-ms-transform: scale(@ratio);
-o-transform: scale(@ratio);
transform: scale(@ratio);
}
.translate(@x: 0, @y: 0) {
-webkit-transform: translate(@x, @y);
-moz-transform: translate(@x, @y);
-ms-transform: translate(@x, @y);
-o-transform: translate(@x, @y);
transform: translate(@x, @y);
}
.skew(@x: 0, @y: 0) {
-webkit-transform: skew(@x, @y);
-moz-transform: skew(@x, @y);
-ms-transform: skew(@x, @y);
-o-transform: skew(@x, @y);
transform: skew(@x, @y);
}
.translate3d(@x: 0, @y: 0, @z: 0) {
-webkit-transform: translate(@x, @y, @z);
-moz-transform: translate(@x, @y, @z);
-ms-transform: translate(@x, @y, @z);
-o-transform: translate(@x, @y, @z);
transform: translate(@x, @y, @z);
}
// Background clipping
// Heads up: FF 3.6 and under need "padding" instead of "padding-box"
.background-clip(@clip) {
-webkit-background-clip: @clip;
-moz-background-clip: @clip;
background-clip: @clip;
}
// Background sizing
.background-size(@size){
-webkit-background-size: @size;
-moz-background-size: @size;
-o-background-size: @size;
background-size: @size;
}
// Box sizing
.box-sizing(@boxmodel) {
-webkit-box-sizing: @boxmodel;
-moz-box-sizing: @boxmodel;
-ms-box-sizing: @boxmodel;
box-sizing: @boxmodel;
}
// User select
// For selecting text on the page
.user-select(@select) {
-webkit-user-select: @select;
-moz-user-select: @select;
-o-user-select: @select;
user-select: @select;
}
// Resize anything
.resizable(@direction: both) {
resize: @direction; // Options: horizontal, vertical, both
overflow: auto; // Safari fix
}
// CSS3 Content Columns
.content-columns(@columnCount, @columnGap: @gridColumnGutter) {
-webkit-column-count: @columnCount;
-moz-column-count: @columnCount;
column-count: @columnCount;
-webkit-column-gap: @columnGap;
-moz-column-gap: @columnGap;
column-gap: @columnGap;
}
// Opacity
.opacity(@opacity: 100) {
opacity: @opacity / 100;
filter: ~"alpha(opacity=@{opacity})";
}
// BACKGROUNDS
// --------------------------------------------------
// Add an alphatransparency value to any background or border color (via Elyse Holladay)
#translucent {
.background(@color: @white, @alpha: 1) {
background-color: hsla(hue(@color), saturation(@color), lightness(@color), @alpha);
}
.border(@color: @white, @alpha: 1) {
border-color: hsla(hue(@color), saturation(@color), lightness(@color), @alpha);
.background-clip(padding-box);
}
}
// Gradient Bar Colors for buttons and alerts
.gradientBar(@primaryColor, @secondaryColor) {
#gradient > .vertical(@primaryColor, @secondaryColor);
border-color: @secondaryColor @secondaryColor darken(@secondaryColor, 15%);
border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) fadein(rgba(0,0,0,.1), 15%);
}
// Gradients
#gradient {
.horizontal(@startColor: #555, @endColor: #333) {
background-color: @endColor;
background-image: -moz-linear-gradient(left, @startColor, @endColor); // FF 3.6+
background-image: -ms-linear-gradient(left, @startColor, @endColor); // IE10
background-image: -webkit-gradient(linear, 0 0, 100% 0, from(@startColor), to(@endColor)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(left, @startColor, @endColor); // Safari 5.1+, Chrome 10+
background-image: -o-linear-gradient(left, @startColor, @endColor); // Opera 11.10
background-image: linear-gradient(left, @startColor, @endColor); // Le standard
background-repeat: repeat-x;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",@startColor,@endColor)); // IE9 and down
}
.vertical(@startColor: #555, @endColor: #333) {
background-color: mix(@startColor, @endColor, 60%);
background-image: -moz-linear-gradient(top, @startColor, @endColor); // FF 3.6+
background-image: -ms-linear-gradient(top, @startColor, @endColor); // IE10
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@startColor), to(@endColor)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(top, @startColor, @endColor); // Safari 5.1+, Chrome 10+
background-image: -o-linear-gradient(top, @startColor, @endColor); // Opera 11.10
background-image: linear-gradient(top, @startColor, @endColor); // The standard
background-repeat: repeat-x;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@startColor,@endColor)); // IE9 and down
}
.directional(@startColor: #555, @endColor: #333, @deg: 45deg) {
background-color: @endColor;
background-repeat: repeat-x;
background-image: -moz-linear-gradient(@deg, @startColor, @endColor); // FF 3.6+
background-image: -ms-linear-gradient(@deg, @startColor, @endColor); // IE10
background-image: -webkit-linear-gradient(@deg, @startColor, @endColor); // Safari 5.1+, Chrome 10+
background-image: -o-linear-gradient(@deg, @startColor, @endColor); // Opera 11.10
background-image: linear-gradient(@deg, @startColor, @endColor); // The standard
}
.vertical-three-colors(@startColor: #00b3ee, @midColor: #7a43b6, @colorStop: 50%, @endColor: #c3325f) {
background-color: mix(@midColor, @endColor, 80%);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@startColor), color-stop(@colorStop, @midColor), to(@endColor));
background-image: -webkit-linear-gradient(@startColor, @midColor @colorStop, @endColor);
background-image: -moz-linear-gradient(top, @startColor, @midColor @colorStop, @endColor);
background-image: -ms-linear-gradient(@startColor, @midColor @colorStop, @endColor);
background-image: -o-linear-gradient(@startColor, @midColor @colorStop, @endColor);
background-image: linear-gradient(@startColor, @midColor @colorStop, @endColor);
background-repeat: no-repeat;
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@startColor,@endColor)); // IE9 and down, gets no color-stop at all for proper fallback
}
.radial(@innerColor: #555, @outerColor: #333) {
background-color: @outerColor;
background-image: -webkit-gradient(radial, center center, 0, center center, 460, from(@innerColor), to(@outerColor));
background-image: -webkit-radial-gradient(circle, @innerColor, @outerColor);
background-image: -moz-radial-gradient(circle, @innerColor, @outerColor);
background-image: -ms-radial-gradient(circle, @innerColor, @outerColor);
background-image: -o-radial-gradient(circle, @innerColor, @outerColor);
background-repeat: no-repeat;
}
.striped(@color, @angle: -45deg) {
background-color: @color;
background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,.15)), color-stop(.75, rgba(255,255,255,.15)), color-stop(.75, transparent), to(transparent));
background-image: -webkit-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
background-image: -moz-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
background-image: -ms-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(@angle, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
}
}
// Reset filters for IE
.reset-filter() {
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
// COMPONENT MIXINS
// --------------------------------------------------
// Horizontal dividers
// -------------------------
// Dividers (basically an hr) within dropdowns and nav lists
.nav-divider() {
height: 1px;
margin: ((@baseLineHeight / 2) - 1) 1px; // 8px 1px
overflow: hidden;
background-color: #e5e5e5;
border-bottom: 1px solid @white;
// IE7 needs a set width since we gave a height. Restricting just
// to IE7 to keep the 1px left/right space in other browsers.
// It is unclear where IE is getting the extra space that we need
// to negative-margin away, but so it goes.
*width: 100%;
*margin: -5px 0 5px;
}
// Button backgrounds
// ------------------
.buttonBackground(@startColor, @endColor) {
// gradientBar will set the background to a pleasing blend of these, to support IE<=9
.gradientBar(@startColor, @endColor);
.reset-filter();
// in these cases the gradient won't cover the background, so we override
&:hover, &:active, &.active, &.disabled, &[disabled] {
background-color: @endColor;
}
// IE 7 + 8 can't handle box-shadow to show active, so we darken a bit ourselves
&:active,
&.active {
background-color: darken(@endColor, 10%) e("\9");
}
}
// Navbar vertical align
// -------------------------
// Vertically center elements in the navbar.
// Example: an element has a height of 30px, so write out `.navbarVerticalAlign(30px);` to calculate the appropriate top margin.
.navbarVerticalAlign(@elementHeight) {
margin-top: (@navbarHeight - @elementHeight) / 2;
}
// Popover arrows
// -------------------------
// For tipsies and popovers
#popoverArrow {
.top(@arrowWidth: 5px, @color: @black) {
bottom: 0;
left: 50%;
margin-left: -@arrowWidth;
border-left: @arrowWidth solid transparent;
border-right: @arrowWidth solid transparent;
border-top: @arrowWidth solid @color;
}
.left(@arrowWidth: 5px, @color: @black) {
top: 50%;
right: 0;
margin-top: -@arrowWidth;
border-top: @arrowWidth solid transparent;
border-bottom: @arrowWidth solid transparent;
border-left: @arrowWidth solid @color;
}
.bottom(@arrowWidth: 5px, @color: @black) {
top: 0;
left: 50%;
margin-left: -@arrowWidth;
border-left: @arrowWidth solid transparent;
border-right: @arrowWidth solid transparent;
border-bottom: @arrowWidth solid @color;
}
.right(@arrowWidth: 5px, @color: @black) {
top: 50%;
left: 0;
margin-top: -@arrowWidth;
border-top: @arrowWidth solid transparent;
border-bottom: @arrowWidth solid transparent;
border-right: @arrowWidth solid @color;
}
}
// Grid System
// -----------
// Centered container element
.container-fixed() {
margin-left: auto;
margin-right: auto;
.clearfix();
}
// Table columns
.tableColumns(@columnSpan: 1) {
float: none; // undo default grid column styles
width: ((@gridColumnWidth) * @columnSpan) + (@gridGutterWidth * (@columnSpan - 1)) - 16; // 16 is total padding on left and right of table cells
margin-left: 0; // undo default grid column styles
}
// Make a Grid
// Use .makeRow and .makeColumn to assign semantic layouts grid system behavior
.makeRow() {
margin-left: @gridGutterWidth * -1;
.clearfix();
}
.makeColumn(@columns: 1) {
float: left;
margin-left: @gridGutterWidth;
width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
}
// The Grid
#grid {
.core (@gridColumnWidth, @gridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~".span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
.offsetX (@index) when (@index > 0) {
(~".offset@{index}") { .offset(@index); }
.offsetX(@index - 1);
}
.offsetX (0) {}
.offset (@columns) {
margin-left: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1)) + (@gridGutterWidth * 2);
}
.span (@columns) {
width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
}
.row {
margin-left: @gridGutterWidth * -1;
.clearfix();
}
[class*="span"] {
float: left;
margin-left: @gridGutterWidth;
}
// Set the container width, and override it for fixed navbars in media queries
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container { .span(@gridColumns); }
// generate .spanX and .offsetX
.spanX (@gridColumns);
.offsetX (@gridColumns);
}
.fluid (@fluidGridColumnWidth, @fluidGridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~"> .span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
.span (@columns) {
width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1));
}
.row-fluid {
width: 100%;
.clearfix();
> [class*="span"] {
float: left;
margin-left: @fluidGridGutterWidth;
}
> [class*="span"]:first-child {
margin-left: 0;
}
// generate .spanX
.spanX (@gridColumns);
}
}
.input(@gridColumnWidth, @gridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~"input.span@{index}, textarea.span@{index}, .uneditable-input.span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
.span(@columns) {
width: ((@gridColumnWidth) * @columns) + (@gridGutterWidth * (@columns - 1)) - 10;
}
input,
textarea,
.uneditable-input {
margin-left: 0; // override margin-left from core grid system
}
// generate .spanX
.spanX (@gridColumns);
}
}

View File

@@ -0,0 +1,90 @@
// MODALS
// ------
// Recalculate z-index where appropriate
.modal-open {
.dropdown-menu { z-index: @zindexDropdown + @zindexModal; }
.dropdown.open { *z-index: @zindexDropdown + @zindexModal; }
.popover { z-index: @zindexPopover + @zindexModal; }
.tooltip { z-index: @zindexTooltip + @zindexModal; }
}
// Background
.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: @zindexModalBackdrop;
background-color: @black;
// Fade for backdrop
&.fade { opacity: 0; }
}
.modal-backdrop,
.modal-backdrop.fade.in {
.opacity(80);
}
// Base modal
.modal {
position: fixed;
top: 50%;
left: 50%;
z-index: @zindexModal;
overflow: auto;
width: 560px;
margin: -250px 0 0 -280px;
background-color: @white;
border: 1px solid #999;
border: 1px solid rgba(0,0,0,.3);
*border: 1px solid #999; /* IE6-7 */
.border-radius(6px);
.box-shadow(0 3px 7px rgba(0,0,0,0.3));
.background-clip(padding-box);
&.fade {
.transition(e('opacity .3s linear, top .3s ease-out'));
top: -25%;
}
&.fade.in { top: 50%; }
}
.modal-header {
padding: 9px 15px;
border-bottom: 1px solid #eee;
// Close icon
.close { margin-top: 2px; }
}
// Body (where all modal content resises)
.modal-body {
overflow-y: auto;
max-height: 400px;
padding: 15px;
}
// Remove bottom margin if need be
.modal-form {
margin-bottom: 0;
}
// Footer (for actions)
.modal-footer {
padding: 14px 15px 15px;
margin-bottom: 0;
text-align: right; // right align buttons
background-color: #f5f5f5;
border-top: 1px solid #ddd;
.border-radius(0 0 6px 6px);
.box-shadow(inset 0 1px 0 @white);
.clearfix(); // clear it in case folks use .pull-* classes on buttons
// Properly space out buttons
.btn + .btn {
margin-left: 5px;
margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
}
// but override that for button groups
.btn-group .btn + .btn {
margin-left: -1px;
}
}

View File

@@ -0,0 +1,341 @@
// NAVBAR (FIXED AND STATIC)
// -------------------------
// COMMON STYLES
// -------------
.navbar {
// Fix for IE7's bad z-indexing so dropdowns don't appear below content that follows the navbar
*position: relative;
*z-index: 2;
overflow: visible;
margin-bottom: @baseLineHeight;
}
// Gradient is applied to it's own element because overflow visible is not honored by IE when filter is present
.navbar-inner {
padding-left: 20px;
padding-right: 20px;
#gradient > .vertical(@navbarBackgroundHighlight, @navbarBackground);
.border-radius(4px);
@shadow: 0 1px 3px rgba(0,0,0,.25), inset 0 -1px 0 rgba(0,0,0,.1);
.box-shadow(@shadow);
}
// Set width to auto for default container
// We then reset it for fixed navbars in the #gridSystem mixin
.navbar .container {
width: auto;
}
// Navbar button for toggling navbar items in responsive layouts
.btn-navbar {
display: none;
float: right;
padding: 7px 10px;
margin-left: 5px;
margin-right: 5px;
.buttonBackground(@navbarBackgroundHighlight, @navbarBackground);
@shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);
.box-shadow(@shadow);
}
.btn-navbar .icon-bar {
display: block;
width: 18px;
height: 2px;
background-color: #f5f5f5;
.border-radius(1px);
.box-shadow(0 1px 0 rgba(0,0,0,.25));
}
.btn-navbar .icon-bar + .icon-bar {
margin-top: 3px;
}
// Override the default collapsed state
.nav-collapse.collapse {
height: auto;
}
// Brand, links, text, and buttons
.navbar {
color: @navbarText;
// Hover and active states
.brand:hover {
text-decoration: none;
}
// Website or project name
.brand {
float: left;
display: block;
padding: 8px 20px 12px;
margin-left: -20px; // negative indent to left-align the text down the page
font-size: 20px;
font-weight: 200;
line-height: 1;
color: @white;
}
// Plain text in topbar
.navbar-text {
margin-bottom: 0;
line-height: @navbarHeight;
}
// Buttons in navbar
.btn,
.btn-group {
.navbarVerticalAlign(30px); // Vertically center in navbar
}
.btn-group .btn {
margin-top: 0; // then undo the margin here so we don't accidentally double it
}
}
// Navbar forms
.navbar-form {
margin-bottom: 0; // remove default bottom margin
.clearfix();
input,
select,
.radio,
.checkbox {
.navbarVerticalAlign(30px); // Vertically center in navbar
}
input,
select {
display: inline-block;
margin-bottom: 0;
}
input[type="image"],
input[type="checkbox"],
input[type="radio"] {
margin-top: 3px;
}
.input-append,
.input-prepend {
margin-top: 6px;
white-space: nowrap; // preven two items from separating within a .navbar-form that has .pull-left
input {
margin-top: 0; // remove the margin on top since it's on the parent
}
}
}
// Navbar search
.navbar-search {
position: relative;
float: left;
.navbarVerticalAlign(28px); // Vertically center in navbar
margin-bottom: 0;
.search-query {
padding: 4px 9px;
#font > .sans-serif(13px, normal, 1);
color: @white;
background-color: @navbarSearchBackground;
border: 1px solid @navbarSearchBorder;
@shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0px rgba(255,255,255,.15);
.box-shadow(@shadow);
.transition(none);
// Placeholder text gets special styles; can't be a grouped selector
&:-moz-placeholder {
color: @navbarSearchPlaceholderColor;
}
&::-webkit-input-placeholder {
color: @navbarSearchPlaceholderColor;
}
// Focus states (we use .focused since IE7-8 and down doesn't support :focus)
&:focus,
&.focused {
padding: 5px 10px;
color: @grayDark;
text-shadow: 0 1px 0 @white;
background-color: @navbarSearchBackgroundFocus;
border: 0;
.box-shadow(0 0 3px rgba(0,0,0,.15));
outline: 0;
}
}
}
// FIXED NAVBAR
// ------------
// Shared (top/bottom) styles
.navbar-fixed-top,
.navbar-fixed-bottom {
position: fixed;
right: 0;
left: 0;
z-index: @zindexFixedNavbar;
margin-bottom: 0; // remove 18px margin for static navbar
}
.navbar-fixed-top .navbar-inner,
.navbar-fixed-bottom .navbar-inner {
padding-left: 0;
padding-right: 0;
.border-radius(0);
}
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
#grid > .core > .span(@gridColumns);
}
// Fixed to top
.navbar-fixed-top {
top: 0;
}
// Fixed to bottom
.navbar-fixed-bottom {
bottom: 0;
}
// NAVIGATION
// ----------
.navbar .nav {
position: relative;
left: 0;
display: block;
float: left;
margin: 0 10px 0 0;
}
.navbar .nav.pull-right {
float: right; // redeclare due to specificity
}
.navbar .nav > li {
display: block;
float: left;
}
// Links
.navbar .nav > li > a {
float: none;
padding: 10px 10px 11px;
line-height: 19px;
color: @navbarLinkColor;
text-decoration: none;
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
}
// Hover
.navbar .nav > li > a:hover {
background-color: @navbarLinkBackgroundHover; // "transparent" is default to differentiate :hover from .active
color: @navbarLinkColorHover;
text-decoration: none;
}
// Active nav items
.navbar .nav .active > a,
.navbar .nav .active > a:hover {
color: @navbarLinkColorActive;
text-decoration: none;
background-color: @navbarLinkBackgroundActive;
}
// Dividers (basically a vertical hr)
.navbar .divider-vertical {
height: @navbarHeight;
width: 1px;
margin: 0 9px;
overflow: hidden;
background-color: @navbarBackground;
border-right: 1px solid @navbarBackgroundHighlight;
}
// Secondary (floated right) nav in topbar
.navbar .nav.pull-right {
margin-left: 10px;
margin-right: 0;
}
// Dropdown menus
// --------------
// Menu position and menu carets
.navbar .dropdown-menu {
margin-top: 1px;
.border-radius(4px);
&:before {
content: '';
display: inline-block;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-bottom-color: @dropdownBorder;
position: absolute;
top: -7px;
left: 9px;
}
&:after {
content: '';
display: inline-block;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid @dropdownBackground;
position: absolute;
top: -6px;
left: 10px;
}
}
// Menu position and menu caret support for dropups via extra dropup class
.navbar-fixed-bottom .dropdown-menu {
&:before {
border-top: 7px solid #ccc;
border-top-color: @dropdownBorder;
border-bottom: 0;
bottom: -7px;
top: auto;
}
&:after {
border-top: 6px solid @dropdownBackground;
border-bottom: 0;
bottom: -6px;
top: auto;
}
}
// Dropdown toggle caret
.navbar .nav .dropdown-toggle .caret,
.navbar .nav .open.dropdown .caret {
border-top-color: @white;
border-bottom-color: @white;
}
.navbar .nav .active .caret {
.opacity(100);
}
// Remove background color from open dropdown
.navbar .nav .open > .dropdown-toggle,
.navbar .nav .active > .dropdown-toggle,
.navbar .nav .open.active > .dropdown-toggle {
background-color: transparent;
}
// Dropdown link on hover
.navbar .nav .active > .dropdown-toggle:hover {
color: @white;
}
// Right aligned menus need alt position
// TODO: rejigger this at some point to simplify the selectors
.navbar .nav.pull-right .dropdown-menu,
.navbar .nav .dropdown-menu.pull-right {
left: auto;
right: 0;
&:before {
left: auto;
right: 12px;
}
&:after {
left: auto;
right: 13px;
}
}

View File

@@ -0,0 +1,363 @@
// NAVIGATIONS
// -----------
// BASE CLASS
// ----------
.nav {
margin-left: 0;
margin-bottom: @baseLineHeight;
list-style: none;
}
// Make links block level
.nav > li > a {
display: block;
}
.nav > li > a:hover {
text-decoration: none;
background-color: @grayLighter;
}
// Nav headers (for dropdowns and lists)
.nav .nav-header {
display: block;
padding: 3px 15px;
font-size: 11px;
font-weight: bold;
line-height: @baseLineHeight;
color: @grayLight;
text-shadow: 0 1px 0 rgba(255,255,255,.5);
text-transform: uppercase;
}
// Space them out when they follow another list item (link)
.nav li + .nav-header {
margin-top: 9px;
}
// NAV LIST
// --------
.nav-list {
padding-left: 15px;
padding-right: 15px;
margin-bottom: 0;
}
.nav-list > li > a,
.nav-list .nav-header {
margin-left: -15px;
margin-right: -15px;
text-shadow: 0 1px 0 rgba(255,255,255,.5);
}
.nav-list > li > a {
padding: 3px 15px;
}
.nav-list > .active > a,
.nav-list > .active > a:hover {
color: @white;
text-shadow: 0 -1px 0 rgba(0,0,0,.2);
background-color: @linkColor;
}
.nav-list [class^="icon-"] {
margin-right: 2px;
}
// Dividers (basically an hr) within the dropdown
.nav-list .divider {
.nav-divider();
}
// TABS AND PILLS
// -------------
// Common styles
.nav-tabs,
.nav-pills {
.clearfix();
}
.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; // keeps the overall height an even number
}
// TABS
// ----
// Give the tabs something to sit on
.nav-tabs {
border-bottom: 1px solid #ddd;
}
// Make the list-items overlay the bottom border
.nav-tabs > li {
margin-bottom: -1px;
}
// Actual tabs (as links)
.nav-tabs > li > a {
padding-top: 8px;
padding-bottom: 8px;
line-height: @baseLineHeight;
border: 1px solid transparent;
.border-radius(4px 4px 0 0);
&:hover {
border-color: @grayLighter @grayLighter #ddd;
}
}
// Active state, and it's :hover to override normal :hover
.nav-tabs > .active > a,
.nav-tabs > .active > a:hover {
color: @gray;
background-color: @white;
border: 1px solid #ddd;
border-bottom-color: transparent;
cursor: default;
}
// PILLS
// -----
// Links rendered as pills
.nav-pills > li > a {
padding-top: 8px;
padding-bottom: 8px;
margin-top: 2px;
margin-bottom: 2px;
.border-radius(5px);
}
// Active state
.nav-pills > .active > a,
.nav-pills > .active > a:hover {
color: @white;
background-color: @linkColor;
}
// STACKED NAV
// -----------
// Stacked tabs and pills
.nav-stacked > li {
float: none;
}
.nav-stacked > li > a {
margin-right: 0; // no need for the gap between nav items
}
// Tabs
.nav-tabs.nav-stacked {
border-bottom: 0;
}
.nav-tabs.nav-stacked > li > a {
border: 1px solid #ddd;
.border-radius(0);
}
.nav-tabs.nav-stacked > li:first-child > a {
.border-radius(4px 4px 0 0);
}
.nav-tabs.nav-stacked > li:last-child > a {
.border-radius(0 0 4px 4px);
}
.nav-tabs.nav-stacked > li > a:hover {
border-color: #ddd;
z-index: 2;
}
// Pills
.nav-pills.nav-stacked > li > a {
margin-bottom: 3px;
}
.nav-pills.nav-stacked > li:last-child > a {
margin-bottom: 1px; // decrease margin to match sizing of stacked tabs
}
// DROPDOWNS
// ---------
// Position the menu
.nav-tabs .dropdown-menu,
.nav-pills .dropdown-menu {
margin-top: 1px;
border-width: 1px;
}
.nav-pills .dropdown-menu {
.border-radius(4px);
}
// Default dropdown links
// -------------------------
// Make carets use linkColor to start
.nav-tabs .dropdown-toggle .caret,
.nav-pills .dropdown-toggle .caret {
border-top-color: @linkColor;
border-bottom-color: @linkColor;
margin-top: 6px;
}
.nav-tabs .dropdown-toggle:hover .caret,
.nav-pills .dropdown-toggle:hover .caret {
border-top-color: @linkColorHover;
border-bottom-color: @linkColorHover;
}
// Active dropdown links
// -------------------------
.nav-tabs .active .dropdown-toggle .caret,
.nav-pills .active .dropdown-toggle .caret {
border-top-color: @grayDark;
border-bottom-color: @grayDark;
}
// Active:hover dropdown links
// -------------------------
.nav > .dropdown.active > a:hover {
color: @black;
cursor: pointer;
}
// Open dropdowns
// -------------------------
.nav-tabs .open .dropdown-toggle,
.nav-pills .open .dropdown-toggle,
.nav > .open.active > a:hover {
color: @white;
background-color: @grayLight;
border-color: @grayLight;
}
.nav .open .caret,
.nav .open.active .caret,
.nav .open a:hover .caret {
border-top-color: @white;
border-bottom-color: @white;
.opacity(100);
}
// Dropdowns in stacked tabs
.tabs-stacked .open > a:hover {
border-color: @grayLight;
}
// TABBABLE
// --------
// COMMON STYLES
// -------------
// Clear any floats
.tabbable {
.clearfix();
}
.tab-content {
display: table; // prevent content from running below tabs
width: 100%;
}
// Remove border on bottom, left, right
.tabs-below .nav-tabs,
.tabs-right .nav-tabs,
.tabs-left .nav-tabs {
border-bottom: 0;
}
// Show/hide tabbable areas
.tab-content > .tab-pane,
.pill-content > .pill-pane {
display: none;
}
.tab-content > .active,
.pill-content > .active {
display: block;
}
// BOTTOM
// ------
.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 {
.border-radius(0 0 4px 4px);
&:hover {
border-bottom-color: transparent;
border-top-color: #ddd;
}
}
.tabs-below .nav-tabs .active > a,
.tabs-below .nav-tabs .active > a:hover {
border-color: transparent #ddd #ddd #ddd;
}
// LEFT & RIGHT
// ------------
// Common styles
.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 on the left
.tabs-left .nav-tabs {
float: left;
margin-right: 19px;
border-right: 1px solid #ddd;
}
.tabs-left .nav-tabs > li > a {
margin-right: -1px;
.border-radius(4px 0 0 4px);
}
.tabs-left .nav-tabs > li > a:hover {
border-color: @grayLighter #ddd @grayLighter @grayLighter;
}
.tabs-left .nav-tabs .active > a,
.tabs-left .nav-tabs .active > a:hover {
border-color: #ddd transparent #ddd #ddd;
*border-right-color: @white;
}
// Tabs on the right
.tabs-right .nav-tabs {
float: right;
margin-left: 19px;
border-left: 1px solid #ddd;
}
.tabs-right .nav-tabs > li > a {
margin-left: -1px;
.border-radius(0 4px 4px 0);
}
.tabs-right .nav-tabs > li > a:hover {
border-color: @grayLighter @grayLighter @grayLighter #ddd;
}
.tabs-right .nav-tabs .active > a,
.tabs-right .nav-tabs .active > a:hover {
border-color: #ddd #ddd #ddd transparent;
*border-left-color: @white;
}

View File

@@ -0,0 +1,36 @@
// PAGER
// -----
.pager {
margin-left: 0;
margin-bottom: @baseLineHeight;
list-style: none;
text-align: center;
.clearfix();
}
.pager li {
display: inline;
}
.pager a {
display: inline-block;
padding: 5px 14px;
background-color: #fff;
border: 1px solid #ddd;
.border-radius(15px);
}
.pager a:hover {
text-decoration: none;
background-color: #f5f5f5;
}
.pager .next a {
float: right;
}
.pager .previous a {
float: left;
}
.pager .disabled a,
.pager .disabled a:hover {
color: @grayLight;
background-color: #fff;
cursor: default;
}

View File

@@ -0,0 +1,56 @@
// PAGINATION
// ----------
.pagination {
height: @baseLineHeight * 2;
margin: @baseLineHeight 0;
}
.pagination ul {
display: inline-block;
.ie7-inline-block();
margin-left: 0;
margin-bottom: 0;
.border-radius(3px);
.box-shadow(0 1px 2px rgba(0,0,0,.05));
}
.pagination li {
display: inline;
}
.pagination a {
float: left;
padding: 0 14px;
line-height: (@baseLineHeight * 2) - 2;
text-decoration: none;
border: 1px solid #ddd;
border-left-width: 0;
}
.pagination a:hover,
.pagination .active a {
background-color: #f5f5f5;
}
.pagination .active a {
color: @grayLight;
cursor: default;
}
.pagination .disabled span,
.pagination .disabled a,
.pagination .disabled a:hover {
color: @grayLight;
background-color: transparent;
cursor: default;
}
.pagination li:first-child a {
border-left-width: 1px;
.border-radius(3px 0 0 3px);
}
.pagination li:last-child a {
.border-radius(0 3px 3px 0);
}
// Centered
.pagination-centered {
text-align: center;
}
.pagination-right {
text-align: right;
}

View File

@@ -0,0 +1,49 @@
// POPOVERS
// --------
.popover {
position: absolute;
top: 0;
left: 0;
z-index: @zindexPopover;
display: none;
padding: 5px;
&.top { margin-top: -5px; }
&.right { margin-left: 5px; }
&.bottom { margin-top: 5px; }
&.left { margin-left: -5px; }
&.top .arrow { #popoverArrow > .top(); }
&.right .arrow { #popoverArrow > .right(); }
&.bottom .arrow { #popoverArrow > .bottom(); }
&.left .arrow { #popoverArrow > .left(); }
.arrow {
position: absolute;
width: 0;
height: 0;
}
}
.popover-inner {
padding: 3px;
width: 280px;
overflow: hidden;
background: @black; // has to be full background declaration for IE fallback
background: rgba(0,0,0,.8);
.border-radius(6px);
.box-shadow(0 3px 7px rgba(0,0,0,0.3));
}
.popover-title {
padding: 9px 15px;
line-height: 1;
background-color: #f5f5f5;
border-bottom:1px solid #eee;
.border-radius(3px 3px 0 0);
}
.popover-content {
padding: 14px;
background-color: @white;
.border-radius(0 0 3px 3px);
.background-clip(padding-box);
p, ul, ol {
margin-bottom: 0;
}
}

View File

@@ -0,0 +1,109 @@
// PROGRESS BARS
// -------------
// ANIMATIONS
// ----------
// Webkit
@-webkit-keyframes progress-bar-stripes {
from { background-position: 0 0; }
to { background-position: 40px 0; }
}
// Firefox
@-moz-keyframes progress-bar-stripes {
from { background-position: 0 0; }
to { background-position: 40px 0; }
}
// IE9
@-ms-keyframes progress-bar-stripes {
from { background-position: 0 0; }
to { background-position: 40px 0; }
}
// Spec
@keyframes progress-bar-stripes {
from { background-position: 0 0; }
to { background-position: 40px 0; }
}
// THE BARS
// --------
// Outer container
.progress {
overflow: hidden;
height: 18px;
margin-bottom: 18px;
#gradient > .vertical(#f5f5f5, #f9f9f9);
.box-shadow(inset 0 1px 2px rgba(0,0,0,.1));
.border-radius(4px);
}
// Bar of progress
.progress .bar {
width: 0%;
height: 18px;
color: @white;
font-size: 12px;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,.25);
#gradient > .vertical(#149bdf, #0480be);
.box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));
.box-sizing(border-box);
.transition(width .6s ease);
}
// Striped bars
.progress-striped .bar {
#gradient > .striped(#149bdf);
.background-size(40px 40px);
}
// Call animation for the active one
.progress.active .bar {
-webkit-animation: progress-bar-stripes 2s linear infinite;
-moz-animation: progress-bar-stripes 2s linear infinite;
animation: progress-bar-stripes 2s linear infinite;
}
// COLORS
// ------
// Danger (red)
.progress-danger .bar {
#gradient > .vertical(#ee5f5b, #c43c35);
}
.progress-danger.progress-striped .bar {
#gradient > .striped(#ee5f5b);
}
// Success (green)
.progress-success .bar {
#gradient > .vertical(#62c462, #57a957);
}
.progress-success.progress-striped .bar {
#gradient > .striped(#62c462);
}
// Info (teal)
.progress-info .bar {
#gradient > .vertical(#5bc0de, #339bb9);
}
.progress-info.progress-striped .bar {
#gradient > .striped(#5bc0de);
}
// Warning (orange)
.progress-warning .bar {
#gradient > .vertical(lighten(@orange, 15%), @orange);
}
.progress-warning.progress-striped .bar {
#gradient > .striped(lighten(@orange, 15%));
}

View File

@@ -0,0 +1,126 @@
// Reset.less
// Adapted from Normalize.css http://github.com/necolas/normalize.css
// ------------------------------------------------------------------------
// Display in IE6-9 and FF3
// -------------------------
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section {
display: block;
}
// Display block in IE6-9 and FF3
// -------------------------
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
// Prevents modern browsers from displaying 'audio' without controls
// -------------------------
audio:not([controls]) {
display: none;
}
// Base settings
// -------------------------
html {
font-size: 100%;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
// Focus states
a:focus {
.tab-focus();
}
// Hover & Active
a:hover,
a:active {
outline: 0;
}
// Prevents sub and sup affecting line-height in all browsers
// -------------------------
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
// Img border in a's and image quality
// -------------------------
img {
height: auto;
border: 0;
-ms-interpolation-mode: bicubic;
vertical-align: middle;
}
// Forms
// -------------------------
// Font size in all browsers, margin changes, misc consistency
button,
input,
select,
textarea {
margin: 0;
font-size: 100%;
vertical-align: middle;
}
button,
input {
*overflow: visible; // Inner spacing ie IE6/7
line-height: normal; // FF3/4 have !important on line-height in UA stylesheet
}
button::-moz-focus-inner,
input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
padding: 0;
border: 0;
}
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
cursor: pointer; // Cursors on all buttons applied consistently
-webkit-appearance: button; // Style clickable inputs in iOS
}
input[type="search"] { // Appearance in Safari/Chrome
-webkit-appearance: textfield;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
}
textarea {
overflow: auto; // Remove vertical scrollbar in IE6-9
vertical-align: top; // Readability and alignment cross-browser
}

View File

@@ -0,0 +1,371 @@
/*!
* Bootstrap Responsive v2.0.2
*
* 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.
*/
// Responsive.less
// For phone and tablet devices
// -------------------------------------------------------------
// REPEAT VARIABLES & MIXINS
// -------------------------
// Required since we compile the responsive stuff separately
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
@import "mixins.less";
// RESPONSIVE CLASSES
// ------------------
// Hide from screenreaders and browsers
// Credit: HTML5 Boilerplate
.hidden {
display: none;
visibility: hidden;
}
// Visibility utilities
// For desktops
.visible-phone { display: none; }
.visible-tablet { display: none; }
.visible-desktop { display: block; }
.hidden-phone { display: block; }
.hidden-tablet { display: block; }
.hidden-desktop { display: none; }
// Phones only
@media (max-width: 767px) {
// Show
.visible-phone { display: block; }
// Hide
.hidden-phone { display: none; }
// Hide everything else
.hidden-desktop { display: block; }
.visible-desktop { display: none; }
}
// Tablets & small desktops only
@media (min-width: 768px) and (max-width: 979px) {
// Show
.visible-tablet { display: block; }
// Hide
.hidden-tablet { display: none; }
// Hide everything else
.hidden-desktop { display: block; }
.visible-desktop { display: none; }
}
// UP TO LANDSCAPE PHONE
// ---------------------
@media (max-width: 480px) {
// Smooth out the collapsing/expanding nav
.nav-collapse {
-webkit-transform: translate3d(0, 0, 0); // activate the GPU
}
// Block level the page header small tag for readability
.page-header h1 small {
display: block;
line-height: @baseLineHeight;
}
// Update checkboxes for iOS
input[type="checkbox"],
input[type="radio"] {
border: 1px solid #ccc;
}
// Remove the horizontal form styles
.form-horizontal .control-group > label {
float: none;
width: auto;
padding-top: 0;
text-align: left;
}
// Move over all input controls and content
.form-horizontal .controls {
margin-left: 0;
}
// Move the options list down to align with labels
.form-horizontal .control-list {
padding-top: 0; // has to be padding because margin collaspes
}
// Move over buttons in .form-actions to align with .controls
.form-horizontal .form-actions {
padding-left: 10px;
padding-right: 10px;
}
// Modals
.modal {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
width: auto;
margin: 0;
&.fade.in { top: auto; }
}
.modal-header .close {
padding: 10px;
margin: -10px;
}
// Carousel
.carousel-caption {
position: static;
}
}
// LANDSCAPE PHONE TO SMALL DESKTOP & PORTRAIT TABLET
// --------------------------------------------------
@media (max-width: 767px) {
// Padding to set content in a bit
body {
padding-left: 20px;
padding-right: 20px;
}
.navbar-fixed-top {
margin-left: -20px;
margin-right: -20px;
}
// GRID & CONTAINERS
// -----------------
// Remove width from containers
.container {
width: auto;
}
// Fluid rows
.row-fluid {
width: 100%;
}
// Undo negative margin on rows
.row {
margin-left: 0;
}
// Make all columns even
.row > [class*="span"],
.row-fluid > [class*="span"] {
float: none;
display: block;
width: auto;
margin: 0;
}
// THUMBNAILS
// ----------
.thumbnails [class*="span"] {
width: auto;
}
// FORM FIELDS
// -----------
// Make span* classes full width
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
.input-block-level();
}
// But don't let it screw up prepend/append inputs
.input-prepend input[class*="span"],
.input-append input[class*="span"] {
width: auto;
}
}
// PORTRAIT TABLET TO DEFAULT DESKTOP
// ----------------------------------
@media (min-width: 768px) and (max-width: 979px) {
// Fixed grid
#grid > .core(42px, 20px);
// Fluid grid
#grid > .fluid(5.801104972%, 2.762430939%);
// Input grid
#grid > .input(42px, 20px);
}
// TABLETS AND BELOW
// -----------------
@media (max-width: 979px) {
// UNFIX THE TOPBAR
// ----------------
// Remove any padding from the body
body {
padding-top: 0;
}
// Unfix the navbar
.navbar-fixed-top {
position: static;
margin-bottom: @baseLineHeight;
}
.navbar-fixed-top .navbar-inner {
padding: 5px;
}
.navbar .container {
width: auto;
padding: 0;
}
// Account for brand name
.navbar .brand {
padding-left: 10px;
padding-right: 10px;
margin: 0 0 0 -5px;
}
// Nav collapse clears brand
.navbar .nav-collapse {
clear: left;
}
// Block-level the nav
.navbar .nav {
float: none;
margin: 0 0 (@baseLineHeight / 2);
}
.navbar .nav > li {
float: none;
}
.navbar .nav > li > a {
margin-bottom: 2px;
}
.navbar .nav > .divider-vertical {
display: none;
}
.navbar .nav .nav-header {
color: @navbarText;
text-shadow: none;
}
// Nav and dropdown links in navbar
.navbar .nav > li > a,
.navbar .dropdown-menu a {
padding: 6px 15px;
font-weight: bold;
color: @navbarLinkColor;
.border-radius(3px);
}
.navbar .dropdown-menu li + li a {
margin-bottom: 2px;
}
.navbar .nav > li > a:hover,
.navbar .dropdown-menu a:hover {
background-color: @navbarBackground;
}
// Dropdowns in the navbar
.navbar .dropdown-menu {
position: static;
top: auto;
left: auto;
float: none;
display: block;
max-width: none;
margin: 0 15px;
padding: 0;
background-color: transparent;
border: none;
.border-radius(0);
.box-shadow(none);
}
.navbar .dropdown-menu:before,
.navbar .dropdown-menu:after {
display: none;
}
.navbar .dropdown-menu .divider {
display: none;
}
// Forms in navbar
.navbar-form,
.navbar-search {
float: none;
padding: (@baseLineHeight / 2) 15px;
margin: (@baseLineHeight / 2) 0;
border-top: 1px solid @navbarBackground;
border-bottom: 1px solid @navbarBackground;
@shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
.box-shadow(@shadow);
}
// Pull right (secondary) nav content
.navbar .nav.pull-right {
float: none;
margin-left: 0;
}
// Static navbar
.navbar-static .navbar-inner {
padding-left: 10px;
padding-right: 10px;
}
// Navbar button
.btn-navbar {
display: block;
}
// Hide everything in the navbar save .brand and toggle button */
.nav-collapse {
overflow: hidden;
height: 0;
}
}
// DEFAULT DESKTOP
// ---------------
@media (min-width: 980px) {
.nav-collapse.collapse {
height: auto !important;
overflow: visible !important;
}
}
// LARGE DESKTOP & UP
// ------------------
@media (min-width: 1200px) {
// Fixed grid
#grid > .core(70px, 30px);
// Fluid grid
#grid > .fluid(5.982905983%, 2.564102564%);
// Input grid
#grid > .input(70px, 30px);
// Thumbnails
.thumbnails {
margin-left: -30px;
}
.thumbnails > li {
margin-left: 30px;
}
}

View File

@@ -0,0 +1,29 @@
// Scaffolding
// Basic and global styles for generating a grid system, structural layout, and page templates
// -------------------------------------------------------------------------------------------
// Body reset
// ----------
body {
margin: 0;
font-family: @baseFontFamily;
font-size: @baseFontSize;
line-height: @baseLineHeight;
color: @textColor;
background-color: @bodyBackground;
}
// Links
// -----
a {
color: @linkColor;
text-decoration: none;
}
a:hover {
color: @linkColorHover;
text-decoration: underline;
}

View File

@@ -0,0 +1,158 @@
// SPRITES
// Glyphs and icons for buttons, nav, and more
// -------------------------------------------
// ICONS
// -----
// All icons receive the styles of the <i> tag with a base class
// of .i and are then given a unique class to add width, height,
// and background-position. Your resulting HTML will look like
// <i class="icon-inbox"></i>.
// For the white version of the icons, just add the .icon-white class:
// <i class="icon-inbox icon-white"></i>
[class^="icon-"],
[class*=" icon-"] {
display: inline-block;
width: 14px;
height: 14px;
line-height: 14px;
vertical-align: text-top;
background-image: url("@{iconSpritePath}");
background-position: 14px 14px;
background-repeat: no-repeat;
.ie7-restore-right-whitespace();
}
.icon-white {
background-image: url("@{iconWhiteSpritePath}");
}
.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; } // 1px off
.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; } // 1px off
.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; } // 1px off
.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; } // 1px off
.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 { 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; } // 1px off
.icon-retweet { background-position: -336px -120px; }
.icon-shopping-cart { background-position: -360px -120px; }
.icon-folder-close { background-position: -384px -120px; }
.icon-folder-open { background-position: -408px -120px; }
.icon-resize-vertical { background-position: -432px -119px; }
.icon-resize-horizontal { background-position: -456px -118px; }

View File

@@ -0,0 +1,159 @@
//
// Tables.less
// Tables for, you guessed it, tabular data
// ----------------------------------------
// BASE TABLES
// -----------------
table {
max-width: 100%;
border-collapse: collapse;
border-spacing: 0;
background-color: @tableBackground;
}
// BASELINE STYLES
// ---------------
.table {
width: 100%;
margin-bottom: @baseLineHeight;
// Cells
th,
td {
padding: 8px;
line-height: @baseLineHeight;
text-align: left;
vertical-align: top;
border-top: 1px solid @tableBorder;
}
th {
font-weight: bold;
}
// Bottom align for column headings
thead th {
vertical-align: bottom;
}
// Remove top border from thead by default
colgroup + thead tr:first-child th,
colgroup + thead tr:first-child td,
thead:first-child tr:first-child th,
thead:first-child tr:first-child td {
border-top: 0;
}
// Account for multiple tbody instances
tbody + tbody {
border-top: 2px solid @tableBorder;
}
}
// CONDENSED TABLE W/ HALF PADDING
// -------------------------------
.table-condensed {
th,
td {
padding: 4px 5px;
}
}
// BORDERED VERSION
// ----------------
.table-bordered {
border: 1px solid @tableBorder;
border-left: 0;
border-collapse: separate; // Done so we can round those corners!
*border-collapse: collapsed; // IE7 can't round corners anyway
.border-radius(4px);
th,
td {
border-left: 1px solid @tableBorder;
}
// Prevent a double border
thead:first-child tr:first-child th,
tbody:first-child tr:first-child th,
tbody:first-child tr:first-child td {
border-top: 0;
}
// For first th or td in the first row in the first thead or tbody
thead:first-child tr:first-child th:first-child,
tbody:first-child tr:first-child td:first-child {
.border-radius(4px 0 0 0);
}
thead:first-child tr:first-child th:last-child,
tbody:first-child tr:first-child td:last-child {
.border-radius(0 4px 0 0);
}
// For first th or td in the first row in the first thead or tbody
thead:last-child tr:last-child th:first-child,
tbody:last-child tr:last-child td:first-child {
.border-radius(0 0 0 4px);
}
thead:last-child tr:last-child th:last-child,
tbody:last-child tr:last-child td:last-child {
.border-radius(0 0 4px 0);
}
}
// ZEBRA-STRIPING
// --------------
// Default zebra-stripe styles (alternating gray and transparent backgrounds)
.table-striped {
tbody {
tr:nth-child(odd) td,
tr:nth-child(odd) th {
background-color: @tableBackgroundAccent;
}
}
}
// HOVER EFFECT
// ------------
// Placed here since it has to come after the potential zebra striping
.table {
tbody tr:hover td,
tbody tr:hover th {
background-color: @tableBackgroundHover;
}
}
// TABLE CELL SIZING
// -----------------
// Change the columns
table {
.span1 { .tableColumns(1); }
.span2 { .tableColumns(2); }
.span3 { .tableColumns(3); }
.span4 { .tableColumns(4); }
.span5 { .tableColumns(5); }
.span6 { .tableColumns(6); }
.span7 { .tableColumns(7); }
.span8 { .tableColumns(8); }
.span9 { .tableColumns(9); }
.span10 { .tableColumns(10); }
.span11 { .tableColumns(11); }
.span12 { .tableColumns(12); }
.span13 { .tableColumns(13); }
.span14 { .tableColumns(14); }
.span15 { .tableColumns(15); }
.span16 { .tableColumns(16); }
.span17 { .tableColumns(17); }
.span18 { .tableColumns(18); }
.span19 { .tableColumns(19); }
.span20 { .tableColumns(20); }
.span21 { .tableColumns(21); }
.span22 { .tableColumns(22); }
.span23 { .tableColumns(23); }
.span24 { .tableColumns(24); }
}

View File

@@ -0,0 +1,35 @@
// THUMBNAILS
// ----------
.thumbnails {
margin-left: -@gridGutterWidth;
list-style: none;
.clearfix();
}
.thumbnails > li {
float: left;
margin: 0 0 @baseLineHeight @gridGutterWidth;
}
.thumbnail {
display: block;
padding: 4px;
line-height: 1;
border: 1px solid #ddd;
.border-radius(4px);
.box-shadow(0 1px 1px rgba(0,0,0,.075));
}
// Add a hover state for linked versions only
a.thumbnail:hover {
border-color: @linkColor;
.box-shadow(0 1px 4px rgba(0,105,214,.25));
}
// Images and captions
.thumbnail > img {
display: block;
max-width: 100%;
margin-left: auto;
margin-right: auto;
}
.thumbnail .caption {
padding: 9px;
}

View File

@@ -0,0 +1,35 @@
// TOOLTIP
// ------=
.tooltip {
position: absolute;
z-index: @zindexTooltip;
display: block;
visibility: visible;
padding: 5px;
font-size: 11px;
.opacity(0);
&.in { .opacity(80); }
&.top { margin-top: -2px; }
&.right { margin-left: 2px; }
&.bottom { margin-top: 2px; }
&.left { margin-left: -2px; }
&.top .tooltip-arrow { #popoverArrow > .top(); }
&.left .tooltip-arrow { #popoverArrow > .left(); }
&.bottom .tooltip-arrow { #popoverArrow > .bottom(); }
&.right .tooltip-arrow { #popoverArrow > .right(); }
}
.tooltip-inner {
max-width: 200px;
padding: 3px 8px;
color: @white;
text-align: center;
text-decoration: none;
background-color: @black;
.border-radius(4px);
}
.tooltip-arrow {
position: absolute;
width: 0;
height: 0;
}

View File

@@ -0,0 +1,234 @@
// Typography.less
// Headings, body text, lists, code, and more for a versatile and durable typography system
// ----------------------------------------------------------------------------------------
// BODY TEXT
// ---------
p {
margin: 0 0 @baseLineHeight / 2;
font-family: @baseFontFamily;
font-size: @baseFontSize;
line-height: @baseLineHeight;
small {
font-size: @baseFontSize - 2;
color: @grayLight;
}
}
.lead {
margin-bottom: @baseLineHeight;
font-size: 20px;
font-weight: 200;
line-height: @baseLineHeight * 1.5;
}
// HEADINGS
// --------
h1, h2, h3, h4, h5, h6 {
margin: 0;
font-family: @headingsFontFamily;
font-weight: @headingsFontWeight;
color: @headingsColor;
text-rendering: optimizelegibility; // Fix the character spacing for headings
small {
font-weight: normal;
color: @grayLight;
}
}
h1 {
font-size: 30px;
line-height: @baseLineHeight * 2;
small {
font-size: 18px;
}
}
h2 {
font-size: 24px;
line-height: @baseLineHeight * 2;
small {
font-size: 18px;
}
}
h3 {
line-height: @baseLineHeight * 1.5;
font-size: 18px;
small {
font-size: 14px;
}
}
h4, h5, h6 {
line-height: @baseLineHeight;
}
h4 {
font-size: 14px;
small {
font-size: 12px;
}
}
h5 {
font-size: 12px;
}
h6 {
font-size: 11px;
color: @grayLight;
text-transform: uppercase;
}
// Page header
.page-header {
padding-bottom: @baseLineHeight - 1;
margin: @baseLineHeight 0;
border-bottom: 1px solid @grayLighter;
}
.page-header h1 {
line-height: 1;
}
// LISTS
// -----
// Unordered and Ordered lists
ul, ol {
padding: 0;
margin: 0 0 @baseLineHeight / 2 25px;
}
ul ul,
ul ol,
ol ol,
ol ul {
margin-bottom: 0;
}
ul {
list-style: disc;
}
ol {
list-style: decimal;
}
li {
line-height: @baseLineHeight;
}
ul.unstyled,
ol.unstyled {
margin-left: 0;
list-style: none;
}
// Description Lists
dl {
margin-bottom: @baseLineHeight;
}
dt,
dd {
line-height: @baseLineHeight;
}
dt {
font-weight: bold;
line-height: @baseLineHeight - 1; // fix jank Helvetica Neue font bug
}
dd {
margin-left: @baseLineHeight / 2;
}
// Horizontal layout (like forms)
.dl-horizontal {
dt {
float: left;
clear: left;
width: 120px;
text-align: right;
}
dd {
margin-left: 130px;
}
}
// MISC
// ----
// Horizontal rules
hr {
margin: @baseLineHeight 0;
border: 0;
border-top: 1px solid @hrBorder;
border-bottom: 1px solid @white;
}
// Emphasis
strong {
font-weight: bold;
}
em {
font-style: italic;
}
.muted {
color: @grayLight;
}
// Abbreviations and acronyms
abbr[title] {
border-bottom: 1px dotted #ddd;
cursor: help;
}
abbr.initialism {
font-size: 90%;
text-transform: uppercase;
}
// Blockquotes
blockquote {
padding: 0 0 0 15px;
margin: 0 0 @baseLineHeight;
border-left: 5px solid @grayLighter;
p {
margin-bottom: 0;
#font > .shorthand(16px,300,@baseLineHeight * 1.25);
}
small {
display: block;
line-height: @baseLineHeight;
color: @grayLight;
&:before {
content: '\2014 \00A0';
}
}
// Float right with text-align: right
&.pull-right {
float: right;
padding-left: 0;
padding-right: 15px;
border-left: 0;
border-right: 5px solid @grayLighter;
p,
small {
text-align: right;
}
}
}
// Quotes
q:before,
q:after,
blockquote:before,
blockquote:after {
content: "";
}
// Addresses
address {
display: block;
margin-bottom: @baseLineHeight;
line-height: @baseLineHeight;
font-style: normal;
}
// Misc
small {
font-size: 100%;
}
cite {
font-style: normal;
}

View File

@@ -0,0 +1,23 @@
// UTILITY CLASSES
// ---------------
// Quick floats
.pull-right {
float: right;
}
.pull-left {
float: left;
}
// Toggling content
.hide {
display: none;
}
.show {
display: block;
}
// Visibility
.invisible {
visibility: hidden;
}

View File

@@ -0,0 +1,201 @@
// Variables.less
// Variables to customize the look and feel of Bootstrap
// -----------------------------------------------------
// GLOBAL VALUES
// --------------------------------------------------
// Grays
// -------------------------
@black: #000;
@grayDarker: #222;
@grayDark: #333;
@gray: #555;
@grayLight: #999;
@grayLighter: #eee;
@white: #fff;
// Accent colors
// -------------------------
@blue: #049cdb;
@blueDark: #0064cd;
@green: #46a546;
@red: #9d261d;
@yellow: #ffc40d;
@orange: #f89406;
@pink: #c3325f;
@purple: #7a43b6;
// Scaffolding
// -------------------------
@bodyBackground: @white;
@textColor: @grayDark;
// Links
// -------------------------
@linkColor: #08c;
@linkColorHover: darken(@linkColor, 15%);
// Typography
// -------------------------
@baseFontSize: 13px;
@baseFontFamily: "Helvetica Neue", Helvetica, Arial, sans-serif;
@baseLineHeight: 18px;
@altFontFamily: Georgia, "Times New Roman", Times, serif;
@headingsFontFamily: inherit; // empty to use BS default, @baseFontFamily
@headingsFontWeight: bold; // instead of browser default, bold
@headingsColor: inherit; // empty to use BS default, @textColor
// Tables
// -------------------------
@tableBackground: transparent; // overall background-color
@tableBackgroundAccent: #f9f9f9; // for striping
@tableBackgroundHover: #f5f5f5; // for hover
@tableBorder: #ddd; // table and cell border
// Buttons
// -------------------------
@btnBackground: @white;
@btnBackgroundHighlight: darken(@white, 10%);
@btnBorder: darken(@white, 20%);
@btnPrimaryBackground: @linkColor;
@btnPrimaryBackgroundHighlight: spin(@btnPrimaryBackground, 15%);
@btnInfoBackground: #5bc0de;
@btnInfoBackgroundHighlight: #2f96b4;
@btnSuccessBackground: #62c462;
@btnSuccessBackgroundHighlight: #51a351;
@btnWarningBackground: lighten(@orange, 15%);
@btnWarningBackgroundHighlight: @orange;
@btnDangerBackground: #ee5f5b;
@btnDangerBackgroundHighlight: #bd362f;
@btnInverseBackground: @gray;
@btnInverseBackgroundHighlight: @grayDarker;
// Forms
// -------------------------
@inputBackground: @white;
@inputBorder: #ccc;
@inputDisabledBackground: @grayLighter;
// Dropdowns
// -------------------------
@dropdownBackground: @white;
@dropdownBorder: rgba(0,0,0,.2);
@dropdownLinkColor: @grayDark;
@dropdownLinkColorHover: @white;
@dropdownLinkBackgroundHover: @linkColor;
// COMPONENT VARIABLES
// --------------------------------------------------
// Z-index master list
// -------------------------
// Used for a bird's eye view of components dependent on the z-axis
// Try to avoid customizing these :)
@zindexDropdown: 1000;
@zindexPopover: 1010;
@zindexTooltip: 1020;
@zindexFixedNavbar: 1030;
@zindexModalBackdrop: 1040;
@zindexModal: 1050;
// Sprite icons path
// -------------------------
@iconSpritePath: "../img/glyphicons-halflings.png";
@iconWhiteSpritePath: "../img/glyphicons-halflings-white.png";
// Input placeholder text color
// -------------------------
@placeholderText: @grayLight;
// Hr border color
// -------------------------
@hrBorder: @grayLighter;
// Navbar
// -------------------------
@navbarHeight: 40px;
@navbarBackground: @grayDarker;
@navbarBackgroundHighlight: @grayDark;
@navbarText: @grayLight;
@navbarLinkColor: @grayLight;
@navbarLinkColorHover: @white;
@navbarLinkColorActive: @navbarLinkColorHover;
@navbarLinkBackgroundHover: transparent;
@navbarLinkBackgroundActive: @navbarBackground;
@navbarSearchBackground: lighten(@navbarBackground, 25%);
@navbarSearchBackgroundFocus: @white;
@navbarSearchBorder: darken(@navbarSearchBackground, 30%);
@navbarSearchPlaceholderColor: #ccc;
// Hero unit
// -------------------------
@heroUnitBackground: @grayLighter;
@heroUnitHeadingColor: inherit;
@heroUnitLeadColor: inherit;
// Form states and alerts
// -------------------------
@warningText: #c09853;
@warningBackground: #fcf8e3;
@warningBorder: darken(spin(@warningBackground, -10), 3%);
@errorText: #b94a48;
@errorBackground: #f2dede;
@errorBorder: darken(spin(@errorBackground, -10), 3%);
@successText: #468847;
@successBackground: #dff0d8;
@successBorder: darken(spin(@successBackground, -10), 5%);
@infoText: #3a87ad;
@infoBackground: #d9edf7;
@infoBorder: darken(spin(@infoBackground, -10), 7%);
// GRID
// --------------------------------------------------
// Default 940px grid
// -------------------------
@gridColumns: 12;
@gridColumnWidth: 60px;
@gridGutterWidth: 20px;
@gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));
// Fluid grid
// -------------------------
@fluidGridColumnWidth: 6.382978723%;
@fluidGridGutterWidth: 2.127659574%;

View File

@@ -0,0 +1,27 @@
// WELLS
// -----
.well {
min-height: 20px;
padding: 19px;
margin-bottom: 20px;
background-color: #f5f5f5;
border: 1px solid #eee;
border: 1px solid rgba(0,0,0,.05);
.border-radius(4px);
.box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
blockquote {
border-color: #ddd;
border-color: rgba(0,0,0,.15);
}
}
// Sizes
.well-large {
padding: 24px;
.border-radius(6px);
}
.well-small {
padding: 9px;
.border-radius(3px);
}

View File

@@ -0,0 +1,9 @@
body, html {
background-color:#D5E6B9;
}
.hero-unit {
background-color: transparent;
}

View File

@@ -0,0 +1,62 @@
.highlight .hll { background-color: #000000 }
.highlight { background: #eeffcc; }
.highlight .c { color: #408090; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #007020 } /* Comment.Preproc */
.highlight .c1 { color: #BBBBBB; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #303030 } /* Generic.Output */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #902000 } /* Keyword.Type */
.highlight .m { color: #208050 } /* Literal.Number */
.highlight .s { color: #80A0D0 } /* Literal.String */
.highlight .na { color: #80A0D0 } /* Name.Attribute */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.highlight .no { color: #60add5 } /* Name.Constant */
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #007020 } /* Name.Exception */
.highlight .nf { color: #06287e } /* Name.Function */
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #bb60d5 } /* Name.Variable */
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #208050 } /* Literal.Number.Float */
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
.highlight .sb { color: #80A0D0 } /* Literal.String.Backtick */
.highlight .sc { color: #80A0D0 } /* Literal.String.Char */
.highlight .sd { color: #BBBBBB; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #80A0D0 } /* Literal.String.Double */
.highlight .se { color: #80A0D0; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #80A0D0 } /* Literal.String.Heredoc */
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
.highlight .sr { color: #235388 } /* Literal.String.Regex */
.highlight .s1 { color: #80A0D0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */

View File

@@ -0,0 +1,292 @@
/*
* HTML5 Boilerplate
*
* What follows is the result of much research on cross-browser styling.
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
* Kroc Camen, and the H5BP dev community and team.
*
* Detailed information about this CSS: h5bp.com/css
*
* ==|== normalize ==========================================================
*/
/* =============================================================================
HTML5 display definitions
========================================================================== */
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; }
[hidden] { display: none; }
/* =============================================================================
Base
========================================================================== */
/*
* 1. Correct text resizing oddly in IE6/7 when body font-size is set using em units
* 2. Prevent iOS text size adjust on device orientation change, without disabling user zoom: h5bp.com/g
*/
html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
html, button, input, select, textarea { font-family: sans-serif; color: #222; }
body { margin: 0; font-size: 1em; line-height: 1.4; }
/*
* Remove text-shadow in selection highlight: h5bp.com/i
* These selection declarations have to be separate
* Also: hot pink! (or customize the background color to match your design)
*/
::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; }
::selection { background: #fe57a1; color: #fff; text-shadow: none; }
/* =============================================================================
Links
========================================================================== */
a { color: #00e; }
a:visited { color: #551a8b; }
a:hover { color: #06e; }
a:focus { outline: thin dotted; }
/* Improve readability when focused and hovered in all browsers: h5bp.com/h */
a:hover, a:active { outline: 0; }
/* =============================================================================
Typography
========================================================================== */
abbr[title] { border-bottom: 1px dotted; }
b, strong { font-weight: bold; }
blockquote { margin: 1em 40px; }
dfn { font-style: italic; }
hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
ins { background: #ff9; color: #000; text-decoration: none; }
mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
/* Redeclare monospace font family: h5bp.com/j */
pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
/* Improve readability of pre-formatted text in all browsers */
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
q { quotes: none; }
q:before, q:after { content: ""; content: none; }
small { font-size: 85%; }
/* Position subscript and superscript content without affecting line-height: h5bp.com/k */
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }
/* =============================================================================
Lists
========================================================================== */
ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
dd { margin: 0 0 0 40px; }
nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
/* =============================================================================
Embedded content
========================================================================== */
/*
* 1. Improve image quality when scaled in IE7: h5bp.com/d
* 2. Remove the gap between images and borders on image containers: h5bp.com/i/440
*/
img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
/*
* Correct overflow not hidden in IE9
*/
svg:not(:root) { overflow: hidden; }
/* =============================================================================
Figures
========================================================================== */
figure { margin: 0; }
/* =============================================================================
Forms
========================================================================== */
form { margin: 0; }
fieldset { border: 0; margin: 0; padding: 0; }
/* Indicate that 'label' will shift focus to the associated form element */
label { cursor: pointer; }
/*
* 1. Correct color not inheriting in IE6/7/8/9
* 2. Correct alignment displayed oddly in IE6/7
*/
legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
/*
* 1. Correct font-size not inheriting in all browsers
* 2. Remove margins in FF3/4 S5 Chrome
* 3. Define consistent vertical alignment display in all browsers
*/
button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
/*
* 1. Define line-height as normal to match FF3/4 (set using !important in the UA stylesheet)
*/
button, input { line-height: normal; }
/*
* 1. Display hand cursor for clickable form elements
* 2. Allow styling of clickable form elements in iOS
* 3. Correct inner spacing displayed oddly in IE7 (doesn't effect IE6)
*/
button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
/*
* Re-set default cursor for disabled elements
*/
button[disabled], input[disabled] { cursor: default; }
/*
* Consistent box sizing and appearance
*/
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
/*
* Remove inner padding and border in FF3/4: h5bp.com/l
*/
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
/*
* 1. Remove default vertical scrollbar in IE6/7/8/9
* 2. Allow only vertical resizing
*/
textarea { overflow: auto; vertical-align: top; resize: vertical; }
/* Colors for form validity */
input:valid, textarea:valid { }
input:invalid, textarea:invalid { background-color: #f0dddd; }
/* =============================================================================
Tables
========================================================================== */
table { border-collapse: collapse; border-spacing: 0; }
td { vertical-align: top; }
/* =============================================================================
Chrome Frame Prompt
========================================================================== */
.chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; }
/* ==|== primary styles =====================================================
Author:
========================================================================== */
/* ==|== media queries ======================================================
EXAMPLE Media Query for Responsive Design.
This example overrides the primary ('mobile first') styles
Modify as content requires.
========================================================================== */
@media only screen and (min-width: 35em) {
/* Style adjustments for viewports that meet the condition */
}
/* ==|== non-semantic helper classes ========================================
Please define your styles before this section.
========================================================================== */
/* For image replacement */
.ir { border: 0; font: 0/0 a; text-shadow: none; color: transparent; background-color: transparent; }
/* Hide from both screenreaders and browsers: h5bp.com/u */
.hidden { display: none !important; visibility: hidden; }
/* Hide only visually, but have it available for screenreaders: h5bp.com/v */
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: h5bp.com/p */
.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
/* Hide visually and from screenreaders, but maintain layout */
.invisible { visibility: hidden; }
/* Contain floats: h5bp.com/q */
.clearfix:before, .clearfix:after { content: ""; display: table; }
.clearfix:after { clear: both; }
.clearfix { *zoom: 1; }
/* ==|== print styles =======================================================
Print styles.
Inlined to avoid required HTTP connection: h5bp.com/r
========================================================================== */
@media print {
* { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */
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: ""; } /* Don't show links for images, or javascript/internal links */
pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
thead { display: table-header-group; } /* h5bp.com/t */
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; }
}

View File

@@ -0,0 +1,245 @@
{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
(sidebars != []) %}
{%- set url_root = pathto('', 1) %}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}
{%- macro script() %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- endmacro %}
{%- macro css() %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{%- endfor %}
{%- endmacro %}
{%- macro sidebar() %}
<div class="sphinxsidebarwrapper">
{%- if sidebars != None %}
{#- new style sidebar: explicitly include/exclude templates #}
{%- for sidebartemplate in sidebars %}
{%- include sidebartemplate %}
{%- endfor %}
{%- else %}
{#- old style sidebars: using blocks -- should be deprecated #}
{%- block sidebartoc %}
{%- include "localtoc.html" %}
{%- endblock %}
{%- block sidebarrel %}
{%- include "relations.html" %}
{%- endblock %}
{%- if customsidebar %}
{%- include customsidebar %}
{%- endif %}
{%- block sidebarsearch %}
{%- include "searchbox.html" %}
{%- endblock %}
{%- endif %}
</div>
{%- endmacro %}
<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!-- Consider adding a manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
{{ metatags }}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{{ css() }}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-1.7.2.min.js"><\/script>')</script>
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
{%- endif %}
<!-- Use the .htaccess and remove these lines to avoid edge case issues.
More info: h5bp.com/i/378 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<!-- Mobile viewport optimized: h5bp.com/viewport -->
<meta name="viewport" content="width=device-width">
<!-- Le styles -->
<link href="{{ pathto('_static/less/bootstrap.less', 1) }}" rel="stylesheet/less">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
<link rel="stylesheet" href="{{ pathto('_static/style.css', 1) }}">
<!-- More ideas for your <head> here: h5bp.com/d/head-Tips -->
<!-- All JavaScript at the bottom, except this Modernizr build.
Modernizr enables HTML5 elements & feature detects for optimal performance.
Create your own custom Modernizr build: www.modernizr.com/download/ -->
<script src="{{ pathto('_static/js/modernizr-2.5.3.min.js', 1) }}"></script>
<script src="{{ pathto('_static/js/less-1.3.0.min.js', 1) }}" type="text/javascript"></script>
<link rel="stylesheet" href="{{ pathto('_static/main.css', 1) }}">
</head>
<body>
<!-- Prompt IE 6 users to install Chrome Frame. Remove this if you support IE 6.
chromium.org/developers/how-tos/chrome-frame-getting-started -->
<!--[if lt IE 7]><p class=chromeframe>Your browser is <em>ancient!</em> <a href="http://browsehappy.com/">Upgrade to a different browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to experience this site.</p><![endif]-->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="{{ pathto(master_doc) }}">Media Vorus</a>
<div class="nav-collapse" id="navigation" class="related">
{{ toctree(collapse=True, maxdepth=-1, titles_only=False) }}
</div>
</div>
</div>
</div>
<div role="main" class="container">
<div class="row-fluid">
<div class="span4">
<img src="{{ pathto('_static/img/MEDIAVORUS.png', 1) }}"/>
{{ sidebar() }}
</div>
<div class="span8">
{%- if next and prev == None %}
<div class="hero-unit">
<h1>Media Vorus</h1>
<p>
A tiny PHP lib for playing with MultiMedia Files
</p>
</div>
{%- endif %}
{{ body }}
</div>
</div>
</div>
{%- block footer %}
<hr/>
<footer class="container">
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
{%- else %}
{% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
{%- endif %}
{%- endif %}
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
{%- if show_sphinx %}
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
{%- endif %}
</footer>
{%- endblock %}
<!-- JavaScript at the bottom for fast page loading -->
<!-- scripts concatenated and minified via build script -->
<script src="{{ pathto('_static/js/plugins.js', 1) }}"></script>
<script src="{{ pathto('_static/js/script.js', 1) }}"></script>
<!-- end scripts -->
<!-- Asynchronous Google Analytics snippet. Change UA-XXXXX-X to be your site's ID.
mathiasbynens.be/notes/async-analytics-snippet -->
{{ script() }}
<script>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-30671300-1']);
_gaq.push(['_setDomainName', 'readthedocs.org']);
_gaq.push(['_setAllowLinker', true]);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

View File

@@ -0,0 +1,12 @@
{#
basic/localtoc.html
~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: local table of contents.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- if display_toc %}
{{ toc }}
{%- endif %}

View File

@@ -0,0 +1,20 @@
{#
basic/searchbox.html
~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: quick search box.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- if pagename != "search" %}
<!--<div id="searchbox" style="display: none" class="well">
<form class="search" action="{{ pathto('search') }}" method="get">
<input placeholder="{{ _('Quick search') }}" class="span2" type="text" name="q" style="margin-bottom:0;" />
<input class="btn btn-primary" type="submit" value="{{ _('Go') }}" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>-->
{%- endif %}

View File

@@ -0,0 +1,83 @@
body, html {
background-color:#D5E6B9;
}
.hero-unit {
background-color: transparent;
}
a.headerlink {
display:none;
}
div.highlight pre {
background-color: #000000;
color:#DDDDDD;
}
.sphinxsidebarwrapper ul {
list-style-type: square;
}
.sphinxsidebarwrapper ul li a{
color: #333333;
font-size:1.05em;
}
h1 {
margin-top: 15px;
}
h2 {
margin-top: 10px;
}
/* -- navigation styles ----- */
#navbar, #menu {
margin-bottom: 10px;
}
#navigation {
min-height: 29px;
line-height: 30px;
display:inline-block;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: normal;
}
#navigation ul {
display: block;
float: left;
left: 0;
margin: 0 10px 0 0;
position: relative;
}
#navigation li {
float: left;
display:block;
line-height:38px;
}
#navigation ul > li > a {
color: #999999;
float: none;
line-height: 19px;
padding: 10px 10px 11px;
text-decoration: none;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
#navigation li a {
padding:3px 8px;
color: #999;
}
#navigation li.current a {
color: #FFFFFF;
}
#navigation li a:hover {
color: #FFFFFF;
}
#navigation li a:hover, #navigation li a {
text-decoration:none;
}
#navigation li, #ddLinks, #menu {
font-size: 14px;
}
/* -------------------------- */

View File

@@ -0,0 +1,10 @@
[theme]
inherit = basic
stylesheet = MediaVorus.css
pygments_style = sphinx
[options]
rightsidebar = false
stickysidebar = false
collapsiblesidebar = false
externalrefs = false

287
vendor/alchemy/mediavorus/docs/conf.py vendored Normal file
View File

@@ -0,0 +1,287 @@
# -*- coding: utf-8 -*-
#
# MediaVorus documentation build configuration file, created by
# sphinx-quickstart on Fri Apr 6 18:36:29 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
#extensions = ['sphinxcontrib.phpdomain']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'MediaVorus'
copyright = u'2012, Romain Neutron'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'MediaVorus'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
# 'github_fork': 'romainneutron/MediaVorus'
}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_themes']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'MediaVorusdoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'MediaVorus.tex', u'MediaVorus Documentation',
u'Romain Neutron', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'mediavorus', u'MediaVorus Documentation',
[u'Romain Neutron'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'MediaVorus', u'MediaVorus Documentation',
u'Romain Neutron', 'MediaVorus', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = u'MediaVorus'
epub_author = u'Romain Neutron'
epub_publisher = u'Romain Neutron'
epub_copyright = u'2012, Romain Neutron'
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
#epub_exclude_files = []
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True

263
vendor/alchemy/mediavorus/docs/index.rst vendored Normal file
View File

@@ -0,0 +1,263 @@
Presentation
============
MediaVorus is a small PHP library wich provide a set of tools to extract every
technical information from multimedia files.
Example
-------
.. code-block:: php
<?php
use MediaVorus\MediaVorus;
use MediaVorus\MediaVorus;
use MediaVorus\Media\Image;
$mediavorus = MediaVorus::create();
$Media = $mediavorus->guess('tests/files/CanonRaw.CR2');
if($Media instanceof Image)
{
echo sprintf("Image was taken with a %f shutter speed", $Media->getShutterSpeed());
}
Goals
-----
MediaVorus is a small PHP library wich provide a set of tools to deal with
multimedia files.
The aim is to provide an abstract layer between the program and the multimedia
file.
First, the need is to analyze multimedia files and get their properties.
In a very next future, we would add metadata mapper to handle various
configurations.
API
===
Guesser
-------
.. code-block:: php
<?php
use MediaVorus\MediaVorus;
$Media = MediaVorus::guess('tests/files/ExifTool.jpg');
//Returns a \Doctrine\Common\Collections\ArrayCollection of Medias
$MediaCollection = MediaVorus::inspectDirectory($dir, $recursive);
Medias
------
Media\\DefaultMedia
*******************
Default Media is the Default container.
This object provides GPS informations :
.. code-block:: php
<?php
use MediaVorus\MediaVorus;
use MediaVorus\Media;
$Media = MediaVorus::guess('somefile.smf');
if($Media instanceof Media\DefaultMedia)
{
/**
* Returns the longitude as a described above
*/
$Media->getLongitude();
/**
* Returns the longitude as a described above
*/
$Media->getLatitude();
/**
* Returns Longitude reference (West or East) and equals to one of the
* Media\DefaultMedia::GPSREF_LONGITUDE_* constants
*/
$Media->getLongitudeRef();
/**
* Returns Latitude reference (North or South) and equals to one of the
* Media\DefaultMedia::GPSREF_LATITUDE_* constants
*/
$Media->getLatitudeRef();
}
Media\\Image
************
Media Image extends the default media.
It has much more methods and provides the following informations :
.. code-block:: php
<?php
use MediaVorus\MediaVorus;
use MediaVorus\Media;
$Media = MediaVorus::guess('tests/files/ExifTool.jpg');
if($Media instanceof Media\Image)
{
/**
* It extends the DefaultMedia
*/
assert($Media instanceof Media\DefaultMedia);
/**
* Returns the width (int)
*/
$Media->getWidth();
/**
* Returns the height (int)
*/
$Media->getHeight();
/**
* Returns the number of channels (int)
*/
$Media->getChannels();
/**
* Returns the focal length (string), not parsed
*/
$Media->getFocalLength();
/**
* Returns the color depth in bits (int)
*/
$Media->getColorDepth();
/**
* Returns the camera model name (string)
*/
$Media->getCameraModel();
/**
* Returns true if the flash has been fired (bool)
*/
$Media->getFlashFired();
/**
* Returns the aperture (string), not parsed
*/
$Media->getAperture();
/**
* Returns the shutter speed (string), not parsed
*/
$Media->getShutterSpeed();
/**
* Returns the orientation (string), one of the Media\Image::ORIENTATION_*
*/
$Media->getOrientation();
/**
* Returns the date when the photos has been taken (string), not parsed
*/
$Media->getCreationDate();
/**
* Returns the hyperfocal distance (string), not parsed
*/
$Media->getHyperfocalDistance();
/**
* Returns the ISO value (int)
*/
$Media->getISO();
/**
* Returns the light value (string), not parsed
*/
$Media->getLightValue();
}
Media serialization
-------------------
All medias are serializable with `JMS Serializer <http://jmsyst.com/libs/serializer>`_.
For example :
.. code-block:: php
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
use JMS\Serializer\SerializerBuilder;
use MediaVorus\MediaVorus;
AnnotationRegistry::registerAutoloadNamespace(
'JMS\Serializer\Annotation', __DIR__.'/vendor/jms/serializer/src'
);
$serializer = SerializerBuilder::create()
->setCacheDir(__DIR__ . '/cache')
->build();
$mediavorus = MediaVorus::create();
print($serializer->serialize($mediavorus->guess('image.jpg'), 'json'));
would result in the following output :
.. code-block:: json
{
"type": "Image",
"raw_image": false,
"multiple_layers": false,
"width": 3264,
"height": 2448,
"channels": 3,
"focal_length": 4.28,
"color_depth": 8,
"camera_model": "iPhone 4S",
"flash_fired": false,
"aperture": 2.4,
"shutter_speed": 0.05,
"orientation": 90,
"creation_date": "2012:03:16 16:29:09",
"hyperfocal_distance": 2.0773522348635,
"ISO": 400,
"light_value": 4.847996906555,
"color_space": "RGB"
}
Silex Service Provider
----------------------
MediaVorus comes bundled with its `Silex Service Provider <silex.sensiolabs.org>`_.
As MediaVorus relies on `PHP-Exiftool <https://github.com/romainneutron/PHPExiftool>`_
and `FFProbe <http://ffmpeg-php.readthedocs.org/>`_, you'll have to register
both bundles to use it :
.. code-block:: php
<?php
use FFMpeg\FFMpegServiceProvider;
use MediaVorus\MediaVorusServiceProvider;
use PHPExiftool\PHPExiftoolServiceProvider;
use Silex\Application;
$app = new Application();
$app->register(new MediaVorusServiceProvider());
$app->register(new PHPExiftoolServiceProvider());
$app->register(new FFMpegServiceProvider());
// you will now have access to $app['mediavorus']
$video = $app['mediavorus']->guess('/path/to/video/file');
.. toctree::
:maxdepth: 1
API
UseCases

190
vendor/alchemy/mediavorus/docs/make.bat vendored Normal file
View File

@@ -0,0 +1,190 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MediaVorus.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MediaVorus.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="true"
verbose="false"
bootstrap="tests/bootstrap.php"
>
<logging>
<log type="coverage-html" target="tests/phpunit_report/report" charset="UTF-8"
yui="true" highlight="false"
lowUpperBound="35" highLowerBound="70"/>
</logging>
<php>
<ini name="display_errors" value="on"/>
</php>
<testsuites>
<testsuite name="MediaVorus Tests Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<blacklist>
<directory>vendor</directory>
<directory>tests</directory>
</blacklist>
</filter>
</phpunit>

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Exception;
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Exception;
class FileNotFoundException extends \Exception implements ExceptionInterface
{
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Exception;
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus;
use MediaVorus\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\File as SymfonyFile;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException as SFFileNotFoundException;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class File extends SymfonyFile
{
public function __construct($path)
{
try {
parent::__construct($path, true);
} catch (SFFileNotFoundException $e) {
throw new FileNotFoundException(sprintf('File %s not found', $path));
}
}
}

View File

@@ -0,0 +1,25 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Filter;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
interface FilterInterface
{
/**
* Return a \Closure with {$key, Media $media} parameters and returns boolean
*/
public function apply();
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Filter;
use MediaVorus\Media\MediaInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class MediaType implements FilterInterface
{
protected $type;
/**
* Filter on Media Type
*
* @param string $type One of the \MediaVorus\Media\Media::TYPE_* constants
*/
public function __construct($type)
{
$this->type = $type;
}
/**
* {@inheritdoc}
*/
public function apply()
{
$type = $this->type;
return function($key, MediaInterface $media) use ($type) {
return $media->getType() === $type;
};
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
use JMS\Serializer\Annotation\VirtualProperty;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class Audio extends DefaultMedia
{
/**
* @VirtualProperty
*
* @return string
*/
public function getType()
{
return self::TYPE_AUDIO;
}
/**
* Get the duration of the audio in seconds, null if unavailable
*
* @VirtualProperty
*
* @return float
*/
public function getDuration()
{
$sources = array('Composite:Duration');
if (null !== $value = $this->findInSources($sources)) {
return (float) $value;
}
return null;
}
}

View File

@@ -0,0 +1,301 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
use FFMpeg\FFProbe;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\VirtualProperty;
use MediaVorus\File;
use MediaVorus\Exception\InvalidArgumentException;
use PHPExiftool\Driver\Metadata\MetadataBag;
use PHPExiftool\Exception\ExceptionInterface as PHPExiftoolExceptionInterface;
use PHPExiftool\Writer;
use PHPExiftool\FileEntity;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*
* @ExclusionPolicy("all")
* @todo declarations of custom filters/getters
*/
class DefaultMedia implements MediaInterface
{
const GPSREF_LONGITUDE_WEST = 'W';
const GPSREF_LONGITUDE_EAST = 'E';
const GPSREF_LATITUDE_NORTH = 'N';
const GPSREF_LATITUDE_SOUTH = 'S';
/**
* @var File
*/
protected $file;
/**
* @var FileEntity
*/
protected $entity;
/**
* @var Writer
*/
protected $writer;
/**
* @var type
*/
protected $temporaryFiles = array();
/**
* @var FFProbe
*/
protected $ffprobe;
/**
* Constructor for Medias
*
* @param File $file
* @param FileEntity $entity
* @return MediaInterface
*/
public function __construct(File $file, FileEntity $entity, Writer $writer, FFProbe $ffprobe = null)
{
$this->file = $file;
$this->entity = $entity;
$this->writer = $writer;
$this->ffprobe = $ffprobe;
return $this;
}
/**
* Destructor
*/
public function __destruct()
{
foreach ($this->temporaryFiles as $file) {
$this->removeTemporaryFile($file);
}
$this->file = $this->entity = $this->temporaryFiles = null;
}
/**
* Return the hash of the empty file (without metadatas)
*
* @param string $algo The algorithm to use, available ones are returned by hash_algos()
* @return string The computed hash
*
* @throws InvalidArgumentException If the algorithm is not supported
*/
public function getHash($algo)
{
if ( ! in_array($algo, hash_algos())) {
throw new InvalidArgumentException(sprintf('Hash %s not supported', $algo));
}
$tmpFile = $this->getTemporaryEmptyFile();
$hash = hash_file($algo, $tmpFile);
$this->removeTemporaryFile($tmpFile);
return $hash;
}
/**
* @VirtualProperty
*
* @return string
*/
public function getType()
{
return 'DefaultMedia';
}
/**
*
* @return \MediaVorus\File
*/
public function getFile()
{
return $this->file;
}
/**
* Get Longitude value
*
* @VirtualProperty
*
* @return float
*/
public function getLongitude()
{
if ($this->getMetadatas()->containsKey('Composite:GPSLongitude')) {
return (float) $this->getMetadatas()->get('Composite:GPSLongitude')->getValue()->asString();
}
return null;
}
/**
* Get Longitude Reference value, one of the GPSREF_LONGITUDE_*
*
* @VirtualProperty
*
* @return string|null
*/
public function getLongitudeRef()
{
if ($this->getMetadatas()->containsKey('Composite:GPSLongitudeRef')) {
switch (strtolower($this->getMetadatas()->get('Composite:GPSLongitudeRef')->getValue()->asString())) {
case 'w':
return self::GPSREF_LONGITUDE_WEST;
break;
case 'e':
return self::GPSREF_LONGITUDE_EAST;
break;
}
}
return null;
}
/**
* Get Latitude value
*
* @VirtualProperty
*
* @return float
*/
public function getLatitude()
{
if ($this->getMetadatas()->containsKey('Composite:GPSLatitude')) {
return (float) $this->getMetadatas()->get('Composite:GPSLatitude')->getValue()->asString();
}
return null;
}
/**
* Get Latitude Reference value, one of the GPSREF_LATITUDE_*
*
* @VirtualProperty
*
* @return string|null
*/
public function getLatitudeRef()
{
if ($this->getMetadatas()->containsKey('Composite:GPSLatitudeRef')) {
switch (strtolower($this->getMetadatas()->get('Composite:GPSLatitudeRef')->getValue()->asString())) {
case 'n':
return self::GPSREF_LATITUDE_NORTH;
break;
case 's':
return self::GPSREF_LATITUDE_SOUTH;
break;
}
}
return null;
}
/**
*
* @return MetadataBag
*/
public function getMetadatas()
{
return $this->entity->getMetadatas();
}
protected function findInSources(Array $sources)
{
foreach ($sources as $source) {
if ($this->getMetadatas()->containsKey($source)) {
return $this->getMetadatas()->get($source)->getValue()->asString();
}
}
return null;
}
protected function castValue($value, $type)
{
if (is_null($value)) {
return null;
}
switch ($type) {
case 'int':
case 'integer':
return (int) $value;
break;
case 'float':
return (float) $value;
break;
case 'string':
return (string) $value;
break;
default:
return $value;
break;
}
}
/**
* Generates a metadatas-free version of the file in the temporary directory
*
* @return string the path file to the temporary file
*/
private function getTemporaryEmptyFile()
{
$tmpFile = tempnam(sys_get_temp_dir(), 'hash');
unlink($tmpFile);
try {
$this->writer->reset();
$this->writer->erase(true);
$this->writer->write($this->file->getPathname(), new MetadataBag(), $tmpFile);
} catch (PHPExiftoolExceptionInterface $e) {
/**
* Some files can not be written by exiftool
*/
copy($this->file->getPathname(), $tmpFile);
}
$this->temporaryFiles[] = $tmpFile;
return $tmpFile;
}
/**
* Remove a file generated by ::getTemporaryEmptyFile
*
* @param String $pathfile The path to the file
* @return DefaultMedia
*/
private function removeTemporaryFile($pathfile)
{
if (false !== $offset = array_search($pathfile, $this->temporaryFiles, true)) {
$file = $this->temporaryFiles[$offset];
if (file_exists($file) && is_writable($file)) {
unlink($file);
array_splice($this->temporaryFiles, $offset, 1);
}
}
return $this;
}
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
class Document extends Image
{
/**
*
* @return string
*/
public function getType()
{
return self::TYPE_DOCUMENT;
}
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
class Flash extends Image
{
/**
*
* @return string
*/
public function getType()
{
return self::TYPE_FLASH;
}
}

View File

@@ -0,0 +1,420 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\VirtualProperty;
use MediaVorus\Utils\RawImageMimeTypeGuesser;
/**
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*
* @todo refactor Meta resolver to an independant object
*/
class Image extends DefaultMedia
{
/**
* Orientation constant Horizontal (normal)
*/
const ORIENTATION_0 = 0;
/**
* Orientation constant Vertical (90 CW)
*/
const ORIENTATION_90 = 90;
/**
* Orientation constant Vertical (270 CW)
*/
const ORIENTATION_270 = 270;
/**
* Orientation constant Horizontal (reversed)
*/
const ORIENTATION_180 = 180;
/**
* Colorspace constant CMYK
*/
const COLORSPACE_CMYK = 'CMYK';
/**
* Colorspace constant RGB
*/
const COLORSPACE_RGB = 'RGB';
/**
* Colorspace constant sRGB
*/
const COLORSPACE_SRGB = 'sRGB';
/**
* Colorspace constant Grayscale
*/
const COLORSPACE_GRAYSCALE = 'Grayscale';
/**
* Colorspace constant RGBA
*/
const COLORSPACE_RGBA = 'RGBA';
/**
* @VirtualProperty
*
* @return string
*/
public function getType()
{
return self::TYPE_IMAGE;
}
/**
* Returns true if the document is a "Raw" image
*
* @VirtualProperty
* @SerializedName("raw_image")
*
* @return boolean
*/
public function isRawImage()
{
return in_array($this->getFile()->getMimeType(), RawImageMimeTypeGuesser::$rawMimeTypes);
}
/**
* Returns true if the document has multiple layers.
* This method is supposed to be used to extract layer 0 with ImageMagick
*
* @VirtualProperty
* @SerializedName("multiple_layers")
*
* @return type
*/
public function hasMultipleLayers()
{
return in_array($this->getFile()->getMimeType(), array(
'image/tiff',
'application/pdf',
'image/psd',
'image/vnd.adobe.photoshop',
'image/photoshop',
'image/ai',
'image/illustrator',
'image/vnd.adobe.illustrator'
));
}
/**
* Return the width, null on error
*
* @VirtualProperty
*
* @return int
*/
public function getWidth()
{
if ($this->getMetadatas()->containsKey('File:ImageWidth')) {
return (int) $this->getMetadatas()->get('File:ImageWidth')->getValue()->asString();
}
if ($this->getMetadatas()->containsKey('Composite:ImageSize')) {
$dimensions = $this->extractFromDimensions(
$this->getMetadatas()->get('Composite:ImageSize')->getValue()->asString()
);
if ($dimensions) {
return (int) $dimensions['width'];
}
}
$sources = array('SubIFD:ImageWidth', 'IFD0:ImageWidth', 'ExifIFD:ExifImageWidth');
return $this->castValue($this->findInSources($sources), 'int');
}
/**
* Return the height, null on error
*
* @VirtualProperty
*
* @return int
*/
public function getHeight()
{
if ($this->getMetadatas()->containsKey('File:ImageHeight')) {
return (int) $this->getMetadatas()->get('File:ImageHeight')->getValue()->asString();
}
if ($this->getMetadatas()->containsKey('Composite:ImageSize')) {
$dimensions = $this->extractFromDimensions(
$this->getMetadatas()->get('Composite:ImageSize')->getValue()->asString()
);
if ($dimensions) {
return (int) $dimensions['height'];
}
}
$sources = array('SubIFD:ImageHeight', 'IFD0:ImageHeight', 'ExifIFD:ExifImageHeight');
return $this->castValue($this->findInSources($sources), 'int');
}
/**
* Return the number of channels (samples per pixel), null on error
*
* @VirtualProperty
*
* @return int
*/
public function getChannels()
{
$sources = array('File:ColorComponents', 'IFD0:SamplesPerPixel');
return $this->castValue($this->findInSources($sources), 'int');
}
/**
* Return the focal length used by the camera in mm, null on error
*
* @VirtualProperty
*
* @return float
*/
public function getFocalLength()
{
$sources = array('ExifIFD:FocalLength', 'XMP-exif:FocalLength');
return $this->castValue($this->findInSources($sources), 'float');
}
/**
* Return the color depth (bits per sample), null on error
*
* @VirtualProperty
*
* @return int
*/
public function getColorDepth()
{
$sources = array('File:BitsPerSample', 'IFD0:BitsPerSample');
return $this->castValue($this->findInSources($sources), 'int');
}
/**
* Return the camera model, null on error
*
* @VirtualProperty
*
* @return string
*/
public function getCameraModel()
{
$sources = array('IFD0:Model', 'IFD0:UniqueCameraModel');
return $this->findInSources($sources);
}
/**
* Return true if the Flash has been fired, false if it has not been
* fired, null if does not know
*
* @VirtualProperty
*
* @return boolean
*/
public function getFlashFired()
{
if (null !== $value = $this->findInSources(array('ExifIFD:Flash', 'Composite:Flash'))) {
switch ($value % 2) {
case 0: // not triggered
return false;
break;
case 1: // triggered
return true;
break;
}
}
return null;
}
/**
* Get Aperture value
*
* @VirtualProperty
*
* @return float
*/
public function getAperture()
{
return $this->castValue($this->findInSources(array('Composite:Aperture')), 'float');
}
/**
* Get ShutterSpeed value in seconds
*
* @VirtualProperty
*
* @return float
*/
public function getShutterSpeed()
{
return $this->castValue($this->findInSources(array('Composite:ShutterSpeed')), 'float');
}
/**
* Returns one one the ORIENTATION_* constants, the degrees value of Orientation
*
* @VirtualProperty
*
* @return int
*/
public function getOrientation()
{
switch ($this->findInSources(array('IFD0:Orientation'))) {
case 6:
return self::ORIENTATION_90;
break;
case 8:
return self::ORIENTATION_270;
break;
case 1:
return self::ORIENTATION_0;
break;
case 3:
return self::ORIENTATION_180;
break;
}
return null;
}
/**
* Returns the Creation Date
*
* @todo rename in getDateTaken to avoid conflicts with the original file
* properties, return a DateTime object
*
* @VirtualProperty
*
* @return string
*/
public function getCreationDate()
{
$sources = array('IPTC:DateCreated', 'ExifIFD:DateTimeOriginal');
return $this->findInSources($sources);
}
/**
* Return the Hyperfocal Distance in meters
*
* @VirtualProperty
*
* @return float
*/
public function getHyperfocalDistance()
{
return $this->castValue($this->findInSources(array('Composite:HyperfocalDistance')), 'float');
}
/**
* Return the ISO value
*
* @VirtualProperty
* @SerializedName("ISO")
*
* @return int
*/
public function getISO()
{
$sources = array('ExifIFD:ISO', 'IFD0:ISO');
return $this->castValue($this->findInSources($sources), 'int');
}
/**
* Return the Light Value
*
* @VirtualProperty
*
* @return float
*/
public function getLightValue()
{
return $this->castValue($this->findInSources(array('Composite:LightValue')), 'float');
}
/**
* Returns the colorspace as one of the COLORSPACE_* constants
*
* @VirtualProperty
*
* @return string
*/
public function getColorSpace()
{
$regexp = '/.*:(colorspace|colormode|colorspacedata|colortype)/i';
foreach ($this->getMetadatas()->filterKeysByRegExp($regexp) as $meta) {
switch (strtolower(trim($meta->getValue()->asString()))) {
case 'cmyk':
return self::COLORSPACE_CMYK;
break;
case 'srgb':
return self::COLORSPACE_SRGB;
break;
case 'rgb':
case '2':
return self::COLORSPACE_RGB;
break;
case 'grayscale':
case '0':
return self::COLORSPACE_GRAYSCALE;
break;
case 'rgba':
case '6':
return self::COLORSPACE_RGBA;
break;
}
}
switch ($this->findInSources(array('File:ColorComponents'))) {
case 1:
return self::COLORSPACE_GRAYSCALE;
break;
case 3:
return self::COLORSPACE_RGB;
break;
case 4:
return self::COLORSPACE_CMYK;
break;
}
return null;
}
/**
* Extract the width and height from a widthXheight serialized value
* Returns an array with width and height keys, null on error
*
* @param type $WidthXHeight
* @return array
*/
protected function extractFromDimensions($WidthXHeight)
{
preg_match("/(\d+)\D+(\d+)/", $WidthXHeight, $values);
if (count($values) === 3 && ctype_digit($values[1]) && ctype_digit($values[2])) {
return array('width' => $values[1], 'height' => $values[2]);
}
return null;
}
}

View File

@@ -0,0 +1,57 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
interface MediaInterface
{
const TYPE_AUDIO = 'Audio';
const TYPE_IMAGE = 'Image';
const TYPE_VIDEO = 'Video';
const TYPE_FLASH = 'Flash';
const TYPE_DOCUMENT = 'Document';
/**
* Return the hash of the `nude` file ; the file is first empty of all its
* metadatas, then the hash is computed.
*
* @see hash_algos()
*
* @param type $algo A valid hash algorithm, see hash_algos function for valid hash names
*
* @return string
*/
public function getHash($algo);
/**
* Return the type
*
* @return string
*/
public function getType();
public function getFile();
public function getMetadatas();
public function getLongitude();
public function getLongitudeRef();
public function getLatitude();
public function getLatitudeRef();
}

View File

@@ -0,0 +1,270 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Media;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\VirtualProperty;
use JMS\Serializer\Annotation\Exclude;
use FFMpeg\Exception\ExceptionInterface as FFMpegException;
use FFMpeg\FFProbe;
use MediaVorus\File;
use PHPExiftool\Writer;
use PHPExiftool\FileEntity;
/**
* @ExclusionPolicy("all")
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class Video extends Image
{
/**
* @VirtualProperty
*
* @return string
*/
public function getType()
{
return self::TYPE_VIDEO;
}
/**
* @VirtualProperty
*
* @return Integer
*/
public function getWidth()
{
$width = parent::getWidth();
if (null === $this->ffprobe) {
return $width;
}
try {
$video = $this->ffprobe
->streams($this->file->getPathname())
->videos()
->first();
return $video->getDimensions()->getWidth();
} catch (FFMpegException $e) {
}
return $width;
}
/**
* @VirtualProperty
*
* @return Integer
*/
public function getHeight()
{
$height = parent::getHeight();
if (null === $this->ffprobe) {
return $height;
}
try {
$video = $this->ffprobe
->streams($this->file->getPathname())
->videos()
->first();
return $video->getDimensions()->getHeight();
} catch (FFMpegException $e) {
}
return $height;
}
/**
* Returns one one the ORIENTATION_* constants, the degrees value of Orientation
*
* @VirtualProperty
*
* @return int
*/
public function getOrientation()
{
switch ($this->findInSources(array('Composite:Rotation'))) {
case 90:
return self::ORIENTATION_90;
break;
case 270:
return self::ORIENTATION_270;
break;
case 0:
return self::ORIENTATION_0;
break;
case 180:
return self::ORIENTATION_180;
break;
}
return null;
}
/**
* Get the duration of the video in seconds, null if unavailable
*
* @VirtualProperty
*
* @return float
*/
public function getDuration()
{
$sources = array('Composite:Duration', 'Flash:Duration', 'QuickTime:Duration', 'Real-PROP:Duration');
if (null !== $value = $this->findInSources($sources)) {
return $this->castValue($value, 'float');
}
if (null === $this->ffprobe) {
return null;
}
$format = $this->ffprobe->format($this->file->getPathname());
if ($format->has('duration')) {
return $this->castValue($format->get('duration'), 'float');
}
return null;
}
/**
* Returns the value of video frame rate, null if not available
*
* @VirtualProperty
*
* @return string
*/
public function getFrameRate()
{
$sources = array('RIFF:FrameRate', 'RIFF:VideoFrameRate', 'Flash:FrameRate');
if (null !== $value = $this->findInSources($sources)) {
return $this->castValue($value, 'float');
}
if (null !== $value = $this->entity->executeQuery('Track1:VideoFrameRate')) {
return $this->castValue($value->asString(), 'float');
}
if (null !== $value = $this->entity->executeQuery('Track2:VideoFrameRate')) {
return $this->castValue($value->asString(), 'float');
}
return null;
}
/**
* Returns the value of audio samplerate, null if not available
*
* @VirtualProperty
*
* @return string
*/
public function getAudioSampleRate()
{
$sources = array('RIFF:AudioSampleRate', 'Flash:AudioSampleRate');
if (null !== $value = $this->findInSources($sources)) {
return $this->castValue($value, 'int');
}
if (null !== $value = $this->entity->executeQuery('Track1:AudioSampleRate')) {
return $this->castValue($value->asString(), 'int');
}
if (null !== $value = $this->entity->executeQuery('Track2:AudioSampleRate')) {
return $this->castValue($value->asString(), 'int');
}
return null;
}
/**
* Returns the name of video codec, null if not available
*
* @VirtualProperty
*
* @return string
*/
public function getVideoCodec()
{
$sources = array('RIFF:AudioSampleRate', 'Flash:VideoEncoding');
if (null !== $value = $this->findInSources($sources)) {
return $this->castValue($value, 'string');
}
if (null !== $value = $this->entity->executeQuery('QuickTime:ComAppleProappsOriginalFormat')) {
return $this->castValue($value->asString(), 'string');
}
if (null !== $value = $this->entity->executeQuery('Track1:CompressorName')) {
return $this->castValue($value->asString(), 'string');
}
if (null !== $value = $this->entity->executeQuery('Track2:CompressorName')) {
return $this->castValue($value->asString(), 'string');
}
if (null !== $value = $this->entity->executeQuery('Track1:CompressorID')) {
return $this->castValue($value->asString(), 'string');
}
if (null !== $value = $this->entity->executeQuery('Track2:CompressorID')) {
return $this->castValue($value->asString(), 'string');
}
return null;
}
/**
* Returns the name of audio codec, null if not available
*
* @VirtualProperty
*
* @return string
*/
public function getAudioCodec()
{
if ($this->getMetadatas()->containsKey('RIFF:AudioCodec')
&& $this->getMetadatas()->containsKey('RIFF:Encoding')
&& $this->getMetadatas()->get('RIFF:AudioCodec')->getValue()->asString() === '') {
return $this->getMetadatas()->get('RIFF:Encoding')->getValue()->asString();
}
if (null !== $value = $this->findInSources(array('Flash:AudioEncoding'))) {
return $this->castValue($value, 'string');
}
if (null !== $VideoCodec = $this->entity->executeQuery('Track1:AudioFormat')) {
return $this->castValue($VideoCodec->asString(), 'string');
}
if (null !== $VideoCodec = $this->entity->executeQuery('Track2:AudioFormat')) {
return $this->castValue($VideoCodec->asString(), 'string');
}
return null;
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus;
use Doctrine\Common\Collections\ArrayCollection;
use MediaVorus\Filter\FilterInterface;
class MediaCollection extends ArrayCollection
{
/**
* Filters a MediaCollection with Filters
*
* @param FilterInterface $filter
* @param Boolean $invert_match
* @return type
*/
public function match(FilterInterface $filter, $invert_match = false)
{
list($with, $without) = $this->partition($filter->apply());
return $invert_match ? $without : $with;
}
}

View File

@@ -0,0 +1,192 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus;
use FFMpeg\FFProbe;
use MediaVorus\MediaCollection;
use MediaVorus\Exception\FileNotFoundException;
use MediaVorus\Media\MediaInterface;
use Monolog\Logger;
use Monolog\Handler\NullHandler;
use PHPExiftool\Reader;
use PHPExiftool\Writer;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class MediaVorus
{
private $reader;
private $writer;
private $ffprobe;
public function __construct(Reader $reader, Writer $writer, FFProbe $ffprobe = null)
{
$this->reader = $reader;
$this->writer = $writer;
$this->ffprobe = $ffprobe;
}
/**
* @return Reader
*/
public function getReader()
{
return $this->reader;
}
/**
* @return Writer
*/
public function getWriter()
{
return $this->writer;
}
/**
* @return FFProbe
*/
public function getFFProbe()
{
return $this->ffprobe;
}
/**
* Build a Media Object given a file
*
* @param string $file
* @return MediaInterface
* @throws FileNotFoundException
*/
public function guess($file)
{
$fileObj = new File($file);
$classname = $this->guessFromMimeType($fileObj->getMimeType());
return new $classname($fileObj, $this->reader->reset()->files($file)->first(), $this->writer, $this->ffprobe);
}
/**
*
* @param \SplFileInfo $dir
* @param type $recursive
*
* @return MediaCollection
*/
public function inspectDirectory($dir, $recursive = false)
{
$this->reader
->reset()
->in($dir)
->followSymLinks();
if ( ! $recursive) {
$this->reader->notRecursive();
}
$files = new MediaCollection();
foreach ($this->reader as $entity) {
$file = new File($entity->getFile());
$classname = $this->guessFromMimeType($file->getMimeType());
$files[] = new $classname($file, $entity, $this->writer, $this->ffprobe);
}
return $files;
}
/**
* Create MediaVorus
*
* @return MediaVorus
*/
public static function create()
{
$logger = new Logger('MediaVorus');
$logger->pushHandler(new NullHandler());
return new static(Reader::create($logger), Writer::create($logger), FFProbe::create(array(), $logger));
}
/**
* Return the corresponding \MediaVorus\Media\* class corresponding to a
* mimetype
*
* @param string $mime
* @return string The name of the MediaType class to use
*/
protected function guessFromMimeType($mime)
{
$mime = strtolower($mime);
switch (true) {
case strpos($mime, 'image/') === 0:
case $mime === 'application/postscript':
case $mime === 'application/illustrator':
return 'MediaVorus\Media\Image';
break;
case strpos($mime, 'video/') === 0:
case $mime === 'application/vnd.rn-realmedia':
case $mime === 'application/mxf':
return 'MediaVorus\Media\Video';
break;
case strpos($mime, 'audio/') === 0:
return 'MediaVorus\Media\Audio';
break;
/**
* @todo Implements Documents
*/
case strpos($mime, 'text/') === 0:
case $mime === 'application/msword':
case $mime === 'application/access':
case $mime === 'application/pdf':
case $mime === 'application/excel':
case $mime === 'application/powerpoint':
case $mime === 'application/vnd.ms-powerpoint':
case $mime === 'application/vnd.ms-excel':
case $mime === 'application/vnd.ms-office':
case $mime === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
case $mime === 'application/vnd.openxmlformats-officedocument.wordprocessingml.template':
case $mime === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
case $mime === 'application/vnd.openxmlformats-officedocument.spreadsheetml.template':
case $mime === 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
case $mime === 'application/vnd.openxmlformats-officedocument.presentationml.template':
case $mime === 'application/vnd.openxmlformats-officedocument.presentationml.slideshow':
case $mime === 'application/vnd.oasis.opendocument.formula':
case $mime === 'application/vnd.oasis.opendocument.text-master':
case $mime === 'application/vnd.oasis.opendocument.database':
case $mime === 'application/vnd.oasis.opendocument.formula':
case $mime === 'application/vnd.oasis.opendocument.chart':
case $mime === 'application/vnd.oasis.opendocument.graphics':
case $mime === 'application/vnd.oasis.opendocument.presentation':
case $mime === 'application/vnd.oasis.opendocument.spreadsheet':
case $mime === 'application/vnd.oasis.opendocument.text':
case $mime === 'application/x-indesign':
return 'MediaVorus\Media\Document';
break;
case $mime === 'application/x-shockwave-flash':
return 'MediaVorus\Media\Flash';
break;
default:
break;
}
return 'MediaVorus\Media\DefaultMedia';
}
}

View File

@@ -0,0 +1,49 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus;
use FFMpeg\Exception\ExecutableNotFoundException;
use MediaVorus\Exception\RuntimeException;
use Silex\Application;
use Silex\ServiceProviderInterface;
class MediaVorusServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}
*/
public function register(Application $app)
{
$app['mediavorus'] = $app->share(function(Application $app) {
$ffprobe = null;
if (isset($app['ffmpeg.ffprobe'])) {
try {
$ffprobe = $app['ffmpeg.ffprobe'];
} catch (ExecutableNotFoundException $e) {
}
}
return new MediaVorus($app['exiftool.reader'], $app['exiftool.writer'], $ffprobe);
});
}
/**
* {@inheritdoc}
*/
public function boot(Application $app)
{
if (!isset($app['exiftool.reader']) || ! isset($app['exiftool.writer'])) {
throw new RuntimeException('MediaVorus Service Provider requires Exiftool Service Provider');
}
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class AudioMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $videoMimeTypes = array(
'ape' => 'audio/x-monkeys-audio',
'mp3' => 'audio/mpeg',
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$videoMimeTypes)) {
return static::$videoMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class DocumentMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $documentMimeTypes = array(
'xls' => 'application/vnd.ms-excel',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$documentMimeTypes)) {
return static::$documentMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class FlashMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $flashMimeTypes = array(
'swf' => 'application/x-shockwave-flash',
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$flashMimeTypes)) {
return static::$flashMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class ImageMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $imageMimeTypes = array(
'heic'=> 'image/heic',
'heif'=> 'image/heif',
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$imageMimeTypes)) {
return static::$imageMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class PostScriptMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $postscriptMimeTypes = array(
'eps' => 'application/postscript',
'ai' => 'application/illustrator',
'indd' => 'application/x-indesign',
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$postscriptMimeTypes)) {
return static::$postscriptMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class RawImageMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $rawMimeTypes = array(
'3fr' => 'image/x-tika-hasselblad',
'arw' => 'image/x-tika-sony',
'bay' => 'image/x-tika-casio',
'cap' => 'image/x-tika-phaseone',
'cr2' => 'image/x-tika-canon',
'crw' => 'image/x-tika-canon',
'dcs' => 'image/x-tika-kodak',
'dcr' => 'image/x-tika-kodak',
'dng' => 'image/x-tika-dng',
'drf' => 'image/x-tika-kodak',
'erf' => 'image/x-tika-epson',
'fff' => 'image/x-tika-imacon',
'iiq' => 'image/x-tika-phaseone',
'kdc' => 'image/x-tika-kodak',
'k25' => 'image/x-tika-kodak',
'mef' => 'image/x-tika-mamiya',
'mos' => 'image/x-tika-leaf',
'mrw' => 'image/x-tika-minolta',
'nef' => 'image/x-tika-nikon',
'nrw' => 'image/x-tika-nikon',
'orf' => 'image/x-tika-olympus',
'pef' => 'image/x-tika-pentax',
'ppm' => 'image/x-portable-pixmap',
'ptx' => 'image/x-tika-pentax',
'pxn' => 'image/x-tika-logitech',
'raf' => 'image/x-tika-fuji',
'raw' => 'image/x-tika-panasonic',
'r3d' => 'image/x-tika-red',
'rw2' => 'image/x-tika-panasonic',
'rwz' => 'image/x-tika-rawzor',
'sr2' => 'image/x-tika-sony',
'srf' => 'image/x-tika-sony',
'x3f' => 'image/x-tika-sigma',
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$rawMimeTypes)) {
return static::$rawMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of MediaVorus.
*
* (c) 2012 Romain Neutron <imprec@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MediaVorus\Utils;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
/**
*
* @author Romain Neutron - imprec@gmail.com
* @license http://opensource.org/licenses/MIT MIT
*/
class VideoMimeTypeGuesser implements MimeTypeGuesserInterface
{
public static $videoMimeTypes = array(
'webm' => 'video/webm',
'ogv' => 'video/ogg',
'mts' => 'video/m2ts',
'mov' => 'video/quicktime',
'm4v' => 'video/m4v'
);
/**
* {@inheritdoc}
*/
public function guess($path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (array_key_exists($extension, static::$videoMimeTypes)) {
return static::$videoMimeTypes[$extension];
}
return null;
}
}

View File

@@ -0,0 +1,11 @@
<?php
$loader = require __DIR__.'/../vendor/autoload.php';
$loader->add('MediaVorus', __DIR__ . '/src');
// PHPUnit 6 introduced a breaking change that
// removed PHPUnit_Framework_TestCase as a base class,
// and replaced it with \PHPUnit\Framework\TestCase
if (!class_exists('\PHPUnit_Framework_TestCase') && class_exists('\PHPUnit\Framework\TestCase')) {
class_alias('\PHPUnit\Framework\TestCase', '\PHPUnit_Framework_TestCase');
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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