{{ page.title }}
+{{ page.title }}
+{{ page.title }}
+ +`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))` +| Alignment | Wrap text | `StyleBuilder::setShouldWrapText(true|false)` + + +## Playing with sheets + +When creating a XLSX or ODS file, it is possible to control which sheet the data will be written into. At any time, you can retrieve or set the current sheet: +```php?start_inline=1 +$firstSheet = $writer->getCurrentSheet(); +$writer->addRow($rowForSheet1); // writes the row to the first sheet + +$newSheet = $writer->addNewSheetAndMakeItCurrent(); +$writer->addRow($rowForSheet2); // writes the row to the new sheet + +$writer->setCurrentSheet($firstSheet); +$writer->addRow($anotherRowForSheet1); // append the row to the first sheet +``` + +It is also possible to retrieve all the sheets currently created: +```php?start_inline=1 +$sheets = $writer->getSheets(); +``` + +If you rely on the sheet's name in your application, you can access it and customize it this way: +```php?start_inline=1 +// Accessing the sheet name when reading +foreach ($reader->getSheetIterator() as $sheet) { + $sheetName = $sheet->getName(); +} + +// Accessing the sheet name when writing +$sheet = $writer->getCurrentSheet(); +$sheetName = $sheet->getName(); + +// Customizing the sheet name when writing +$sheet = $writer->getCurrentSheet(); +$sheet->setName('My custom name'); +``` + +> Please note that Excel has some restrictions on the sheet's name: +> * it must not be blank +> * it must not exceed 31 characters +> * it must not contain these characters: \ / ? * : [ or ] +> * it must not start or end with a single quote +> * it must be unique +> +> Handling these restrictions is the developer's responsibility. {{ site.spout_html }} does not try to automatically change the sheet's name, as one may rely on this name to be exactly what was passed in. + +Finally, it is possible to know which sheet was active when the spreadsheet was last saved. This can be useful if you are only interested in processing the one sheet that was last focused. +```php?start_inline=1 +foreach ($reader->getSheetIterator() as $sheet) { + // only process data for the active sheet + if ($sheet->isActive()) { + // do something... + } +} +``` + +## Fluent interface + +Because fluent interfaces are great, you can use them with {{ site.spout_html }}: +```php?start_inline=1 +use Box\Spout\Writer\WriterFactory; +use Box\Spout\Common\Type; + +$writer = WriterFactory::create(Type::XLSX); +$writer->setTempFolder($customTempFolderPath) + ->setShouldUseInlineStrings(true) + ->openToFile($filePath) + ->addRow($headerRow) + ->addRows($dataRows) + ->close(); +``` diff --git a/docs/_pages/faq.md b/docs/_pages/faq.md new file mode 100644 index 0000000..aa21806 --- /dev/null +++ b/docs/_pages/faq.md @@ -0,0 +1,30 @@ +--- +layout: page +title: Frequently Asked Questions +permalink: /faq/ +--- + +### How can Spout handle such large data sets and still use less than 3MB of memory? + +When writing data, Spout is streaming the data to files, one or few lines at a time. That means that it only keeps in memory the few rows that it needs to write. Once written, the memory is freed. + +Same goes with reading. Only one row at a time is stored in memory. A special technique is used to handle shared strings in XLSX, storing them - if needed - into several small temporary files that allows fast access. + +### How long does it take to generate a file with X rows? + +Here are a few numbers regarding the performance of Spout: + +| Type | Action | 2,000 rows (6,000 cells) | 200,000 rows (600,000 cells) | 2,000,000 rows (6,000,000 cells) | +|------|-------------------------------|--------------------------|------------------------------|----------------------------------| +| CSV | Read | < 1 second | 4 seconds | 2-3 minutes | +| | Write | < 1 second | 2 seconds | 2-3 minutes | +| XLSX | Read
*inline strings* | < 1 second | 35-40 seconds | 18-20 minutes | +| | Read
*shared strings* | 1 second | 1-2 minutes | 35-40 minutes | +| | Write | 1 second | 20-25 seconds | 8-10 minutes | +| ODS | Read | 1 second | 1-2 minutes | 5-6 minutes | +| | Write | < 1 second | 35-40 seconds | 5-6 minutes | + +### Does Spout support charts or formulas? + +No. This is a compromise to keep memory usage low. Charts and formulas requires data to be kept in memory in order to be used. +So the larger the file would be, the more memory would be consumed, preventing your code to scale well. diff --git a/docs/_pages/getting-started.md b/docs/_pages/getting-started.md new file mode 100755 index 0000000..49fe0fc --- /dev/null +++ b/docs/_pages/getting-started.md @@ -0,0 +1,96 @@ +--- +layout: doc +title: Getting Started +permalink: /getting-started/ +--- + +This guide will help you install {{ site.spout_html }} and teach you how to use it. + +## Requirements + +* PHP version 5.4.0 or higher +* PHP extension `php_zip` enabled +* PHP extension `php_xmlreader` enabled + + +## Installation + +### Composer (recommended) + +{{ site.spout_html }} can be installed directly from [Composer](https://getcomposer.org/). + +Run the following command: +```powershell +$ composer require box/spout +``` + +### Manual installation + +If you can't use Composer, no worries! You can still install {{ site.spout_html }} manually. + +> Before starting, make sure your system meets the [requirements](#requirements). + +1. Download the source code from the [Releases page](https://github.com/box/spout/releases) +2. Extract the downloaded content into your project. +3. Add this code to the top controller (e.g. index.php) or wherever it may be more appropriate: + +```php?start_inline=1 +// don't forget to change the path! +require_once '[PATH/TO]/src/Spout/Autoloader/autoload.php'; +``` + + +## Basic usage + +### Reader + +Regardless of the file type, the interface to read a file is always the same: + +```php?start_inline=1 +use Box\Spout\Reader\ReaderFactory; +use Box\Spout\Common\Type; + +$reader = ReaderFactory::create(Type::XLSX); // for XLSX files +//$reader = ReaderFactory::create(Type::CSV); // for CSV files +//$reader = ReaderFactory::create(Type::ODS); // for ODS files + +$reader->open($filePath); + +foreach ($reader->getSheetIterator() as $sheet) { + foreach ($sheet->getRowIterator() as $row) { + // do stuff with the row + } +} + +$reader->close(); +``` + +If there are multiple sheets in the file, the reader will read all of them sequentially. + +### Writer + +As with the reader, there is one common interface to write data to a file: + +```php?start_inline=1 +use Box\Spout\Writer\WriterFactory; +use Box\Spout\Common\Type; + +$writer = WriterFactory::create(Type::XLSX); // for XLSX files +//$writer = WriterFactory::create(Type::CSV); // for CSV files +//$writer = WriterFactory::create(Type::ODS); // for ODS files + +$writer->openToFile($filePath); // write data to a file or to a PHP stream +//$writer->openToBrowser($fileName); // stream data directly to the browser + +$writer->addRow($singleRow); // add a row at a time +$writer->addRows($multipleRows); // add multiple rows at a time + +$writer->close(); +``` + +For XLSX and ODS files, the number of rows per sheet is limited to *1,048,576*. By default, once this limit is reached, the writer will automatically create a new sheet and continue writing data into it. + + +## Advanced usage + +You can do a lot more with {{ site.spout_html }}! Check out the [full documentation]({{ site.github.url }}/docs/) to learn about all the features. diff --git a/docs/_pages/guides.md b/docs/_pages/guides.md new file mode 100644 index 0000000..5746c8c --- /dev/null +++ b/docs/_pages/guides.md @@ -0,0 +1,19 @@ +--- +layout: page +title: Guides +permalink: /guides/ +--- + +These guides focus on common and more advanced usages of {{ site.spout_html }}.
+If you are just starting with {{ site.spout_html }}, check out the [Getting Started page]({{ site.github.url }}/getting-started/) and the [Documentation]({{ site.github.url }}/docs/) first. + +{% assign pages=site.pages | sort: 'path' %} +
-
+{% for page in pages %}
+ {% if page.title and page.category contains 'guide' %}
+
- + {{ page.title }} + + {% endif %} +{% endfor %} +
' . $cell . ' | '; + }, $row)); + $content .= '
'; + } + + $reader->close(); + + // The response is sent to the browser + // once the entire file has been read. + $response = new Response($content); + $response->headers->set('Content-Type', 'text/html'); + + return $response; + } +} +``` + +Converting a regular controller to return a `StreamedResponse` is super easy! This is what it looks like after conversion: + +```php?start_inline=1 +class MyStreamController extends Controller +{ + // See below how it is used. + const FLUSH_THRESHOLD = 100; + + /** + * @Route("/spreadsheet/stream") + */ + public function readAction() + { + $filePath = '/path/to/static/file.xlsx'; + + // We'll now return a StreamedResponse. + $response = new StreamedResponse(); + $response->headers->set('Content-Type', 'text/html'); + + // Instead of a string, the streamed response will execute + // a callback function to retrieve data chunks. + $response->setCallback(function() use ($filePath) { + // Same code goes inside the callback. + $reader = ReaderFactory::create(Type::XLSX); + $reader->open($filePath); + + $i = 0; + foreach ($reader->getSheetIterator() as $sheet) { + // The main difference with the regular response is + // that the content is now echo'ed, not appended. + echo '
' . $cell . ' | '; + }, $row)); + echo '
'; + } + + $reader->close(); + }); + + return $response; + } +} +``` diff --git a/docs/_pages/index.md b/docs/_pages/index.md new file mode 100644 index 0000000..a2da586 --- /dev/null +++ b/docs/_pages/index.md @@ -0,0 +1,10 @@ +--- +layout: default +banner: true +title: Spout - Read and write spreadsheets, quickly and at scale +permalink: / +--- + +{% include section-supported-spreadsheet-types.html %} +{% include section-fast-and-scalable.html %} +{% include section-why-use-spout.html %} diff --git a/docs/_sass/_base.scss b/docs/_sass/_base.scss new file mode 100755 index 0000000..29116c5 --- /dev/null +++ b/docs/_sass/_base.scss @@ -0,0 +1,278 @@ +/** + * Reset some basic elements + */ +body, h1, h2, h3, h4, h5, h6, +p, blockquote, pre, hr, +dl, dd, ol, ul, figure { + margin: 0; + padding: 0; +} + + + +/** + * Basic styling + */ +body { + font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family; + color: $text-color; + background-color: $background-color; + -webkit-text-size-adjust: 100%; + -webkit-font-feature-settings: "kern" 1; + -moz-font-feature-settings: "kern" 1; + -o-font-feature-settings: "kern" 1; + font-feature-settings: "kern" 1; + font-kerning: normal; +} + + + +/** + * Set `margin-bottom` to maintain vertical rhythm + */ +h1, h2, h3, h4, h5, h6, +p, blockquote, pre, +ul, ol, dl, figure, +%vertical-rhythm { + margin-bottom: $spacing-unit / 2; +} + +h1:not(:nth-child(1)), h2:not(:nth-child(1)), h3:not(:nth-child(1)), h4:not(:nth-child(1)), h5:not(:nth-child(1)), h6:not(:nth-child(1)) { + margin-top: $spacing-unit; +} + + + +/** + * Tables + */ +table { + display: block; + width: 100%; + overflow: auto; + margin-top: 0; + margin-bottom: 16px; + border-spacing: 0; + border-collapse: collapse; + + th, td { + padding: 6px 13px; + border: 1px solid #dfe2e5; + } + + tr { + background-color: #fff; + border-top: 1px solid #c6cbd1; + + &:nth-child(2n) { + background-color: #f6f8fa; + } + } + + th { + font-weight: 500; + } +} + + + +/** + * Images + */ +img { + max-width: 100%; + vertical-align: middle; +} + + + +/** + * Figures + */ +figure > img { + display: block; +} + +figcaption { + font-size: $small-font-size; +} + + + +/** + * Lists + */ +ul, ol { + margin-left: $spacing-unit; +} + +li { + > ul, + > ol { + margin-bottom: 0; + } +} + + + +/** + * Headings + */ +h1, h2, h3, h4, h5, h6 { + font-weight: $base-font-weight; +} + +h1 { + font-size: 3em; +} + +h2 { + font-size: 2em; +} + + +/** + * Links + */ +a { + color: $brand-color; + text-decoration: none; + font-weight: $base-font-weight; + + &:visited { + color: lighten($brand-color, 15%); + } + + &:hover { + color: $text-color; + text-decoration: underline; + } +} + + + +/** + * Blockquotes + */ +blockquote { + color: $grey-color; + border-left: 4px solid lighten($brand-color, 65%); + padding: $spacing-unit / 3 $spacing-unit / 2; + font-style: italic; + font-weight: 200; + + > :last-child { + margin-bottom: 0; + } +} + + + +/** + * Code formatting + */ +pre, +code { + font-size: 15px; + // border: 1px solid darken($code-color, 5%); + border-radius: 3px; + // background-color: $code-color; +} + +code { + padding: 1px 5px; +} + +pre { + padding: 8px 12px; + overflow-x: auto; + + > code { + border: 0; + padding-right: 0; + padding-left: 0; + } +} + + + +/** + * Wrapper + */ +.wrapper { + max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2)); + max-width: calc(#{$content-width} - (#{$spacing-unit} * 2)); + margin-right: auto; + margin-left: auto; + padding-right: $spacing-unit; + padding-left: $spacing-unit; + @extend %clearfix; + + @include media-query($on-laptop) { + max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit})); + max-width: calc(#{$content-width} - (#{$spacing-unit})); + padding-right: $spacing-unit / 2; + padding-left: $spacing-unit / 2; + } +} + + + +/** + * Clearfix + */ +%clearfix { + + &:after { + content: ""; + display: table; + clear: both; + } +} + + + +/** + * Icons + */ +.icon { + + > svg { + display: inline-block; + width: 16px; + height: 16px; + vertical-align: middle; + + path { + fill: $grey-color; + } + } +} + +.pull-left { + float: left; +} + +.pull-right { + float: right; +} + + +.vertical-align-middle { +// position: relative; +// top: 50%; +// transform: translateY(50%); + display: flex; + justify-content: center; + align-items: center; + +} + +.mrl { margin-right: 20px; } +.mll { margin-left: 20px; } +.mbl { margin-bottom: 20px; } +.text-center { text-align: center; } + +.light-em { + font-weight: $base-font-weight + 100; +} diff --git a/docs/_sass/_index.scss b/docs/_sass/_index.scss new file mode 100755 index 0000000..a3b9744 --- /dev/null +++ b/docs/_sass/_index.scss @@ -0,0 +1,79 @@ +.spout { + font-variant: small-caps; +} + +.section { + padding: $spacing-unit 0; + border-bottom: 1px solid $grey-color-light; + + &.last-section { + border-bottom: none; + } + + .section-title { + text-align: center; + } + + .description { + width: 600px; + } + + &.centered .description { + text-align: center; + } + + .icons { + text-align: center; + + img { + margin: 10px 20px; + } + } + + &.section-odd { + background-color: rgba($grey-color, 0.0); + } + + &.section-even { + background-color: $grey-color-very-light; + } + + .btn-wrapper { + margin: $spacing-unit 0; + text-align: center; + + .btn { + border-radius: 5px; + border: 1px solid; + background: $brand-color; + box-shadow: none; + color: white; + font-size: 20px; + padding: 15px 30px; + text-decoration: none; + cursor: pointer; + font-weight: 500; + } + + .btn:hover { + background: darken($brand-color, 10%); + } + + .page-link:hover { + text-decoration: none; + } + } +} + +.feature-list { + list-style: none; + padding: 0; + margin: 0; +} + +.feature-check { + background: url("../images/blue-check-mark.png") no-repeat left top; + background-size: 15px 15px; + background-position-y: 4px; + padding-left: 25px; +} diff --git a/docs/_sass/_layout.scss b/docs/_sass/_layout.scss new file mode 100755 index 0000000..b6e6b8b --- /dev/null +++ b/docs/_sass/_layout.scss @@ -0,0 +1,406 @@ +/** + * Site header + */ +.site-header { + border-bottom: 1px solid lighten($brand-color, 15%); + min-height: 56px; + + // Positioning context for the mobile navigation icon + position: relative; +} + +.site-search { + padding-right: 10px; +} + +.site-title { + font-size: 26px; + font-weight: 300; + line-height: 56px; + letter-spacing: -1px; + margin-bottom: 0; + float: left; + + &, + &:visited { + color: $grey-color-dark; + } +} + +.site-nav { + float: right; + line-height: 56px; + + .menu-icon { + display: none; + } + + .page-link { + color: $grey-color; + line-height: $base-line-height; + + // Gaps between nav items, but not on the last one + &:not(:last-child) { + margin-right: 20px; + } + } + + @include media-query($on-palm) { + position: absolute; + top: 9px; + right: $spacing-unit / 2; + background-color: $background-color; + border: 1px solid $grey-color-light; + border-radius: 5px; + text-align: right; + + .menu-icon { + display: block; + float: right; + width: 36px; + height: 26px; + line-height: 0; + padding-top: 10px; + text-align: center; + + > svg { + width: 18px; + height: 15px; + + path { + fill: $grey-color-dark; + } + } + } + + .trigger { + clear: both; + display: none; + } + + &:hover .trigger { + display: block; + padding-bottom: 5px; + } + + .page-link { + display: block; + padding: 5px 10px; + + &:not(:last-child) { + margin-right: 0; + } + margin-left: 20px; + } + } +} + +.site-banner { + width: 100%; + background: $brand-color; + height: 340px; + color: white; + + .wrapper { + height: 100%; + background: url('../images/logo.png'); + background-size: 30%; + background-repeat: no-repeat; + background-position: 95% center; + justify-content: flex-start; + } + + .tag-line { + font-size: 2.8em; + line-height: 1.1em; + width: 60%; + } + + @include media-query($on-palm) { + height: 240px; + + .tag-line { + font-size: 1.8em; + } + } +} + + + +/** + * Site footer + */ +.site-footer { + background: $grey-color-dark; + color: $grey-color-light; + border-top: 1px solid $grey-color-light; + padding: $spacing-unit 0; + margin-top: $spacing-unit; + + a { + color: $grey-color-very-light; + } + + .contact-list, + .social-media-list { + list-style: none; + margin-left: 0; + + li { + margin-bottom: 2px; + } + } + + .footer-col-wrapper { + font-size: 15px; + // color: $grey-color; + margin-left: -$spacing-unit / 2; + @extend %clearfix; + } + + .footer-col { + float: left; + margin-bottom: $spacing-unit / 2; + padding-left: $spacing-unit / 2; + } + + .footer-col-1 { + width: -webkit-calc(35% - (#{$spacing-unit} / 2)); + width: calc(35% - (#{$spacing-unit} / 2)); + } + + .footer-col-2 { + width: -webkit-calc(25% - (#{$spacing-unit} / 2)); + width: calc(25% - (#{$spacing-unit} / 2)); + } + + .footer-col-3 { + width: -webkit-calc(40% - (#{$spacing-unit} / 2)); + width: calc(40% - (#{$spacing-unit} / 2)); + } + + @include media-query($on-laptop) { + .footer-col-1, + .footer-col-2 { + width: -webkit-calc(50% - (#{$spacing-unit} / 2)); + width: calc(50% - (#{$spacing-unit} / 2)); + } + + .footer-col-3 { + width: -webkit-calc(100% - (#{$spacing-unit} / 2)); + width: calc(100% - (#{$spacing-unit} / 2)); + } + } + + @include media-query($on-palm) { + .footer-col { + float: none; + width: -webkit-calc(100% - (#{$spacing-unit} / 2)); + width: calc(100% - (#{$spacing-unit} / 2)); + } + } +} + + +/** + * Page content + */ +.page-content { + padding: $spacing-unit 0; +} + +.page-heading { + font-size: 20px; +} + +.post-list { + margin-left: 0; + list-style: none; + + > li { + margin-bottom: $spacing-unit; + } +} + +.post-meta { + font-size: $small-font-size; + color: $grey-color; +} + +.post-link { + display: block; + font-size: 24px; +} + + + +/** + * Posts + */ +.post-header { + margin-bottom: $spacing-unit; + padding-top: $spacing-unit; +} + +.post-title { + font-size: 42px; + letter-spacing: -1px; + line-height: 1; + + @include media-query($on-laptop) { + font-size: 36px; + } +} + +.post-content { + margin-bottom: $spacing-unit; + + h2 { + font-size: 32px; + + @include media-query($on-laptop) { + font-size: 28px; + } + } + + h3 { + font-size: 26px; + + @include media-query($on-laptop) { + font-size: 22px; + } + } + + h4 { + font-size: 20px; + + @include media-query($on-laptop) { + font-size: 18px; + } + } +} + +$table-of-content-width: 250px; + +.table-of-content { + position: absolute; + left: 100px; + width: $table-of-content-width; +} + +.table-of-content.affix-top { + position: absolute; + top: 70px; +} + +.table-of-content.affix-bottom { + position: absolute; + bottom: 300; +} + +.table-of-content.affix { + position: fixed; + top: 30px; +} + +.table-of-content a.h1 { + font-weight: 600; +} + +.table-of-content a.h2 { + font-weight: 400; + font-size: 14px; + position: relative; + left: 10px; +} + +.table-of-content a.h3 { + font-size: 12px; + position: relative; + left: 20px; +} + + +// TODO +@include media-query($on-laptop-big+$table-of-content-width) { + .table-of-content { + left: 20px; + } +} + +@include media-query($on-laptop-big) { + .table-of-content { + display: none; + } +} + +@include media-query($on-laptop) { + .table-of-content { + display: none; + } +} + +/* search */ +input#algolia-doc-search { + background: transparent url("/images/search.png") no-repeat 10px center; + background-size: 16px 16px; + position: relative; + vertical-align: top; + margin-left: 10px; + padding: 0 10px; + padding-left: 35px; + height: 30px; + margin-top: 10px; + font-size: 16px; + line-height: 20px; + background-color: #fff; + border-radius: 4px; + color: #333; + outline: none; + width: 100px; + transition: width .2s ease; + box-shadow: none; + border: 1px solid #ddd; +} + +input#algolia-doc-search:focus { + width: 200px; +} + + /* Bottom border of each suggestion */ +.algolia-docsearch-suggestion { + border-bottom-color: $brand-color; +} +/* Main category headers */ +.algolia-docsearch-suggestion--category-header { + background-color: lighten($brand-color, 20%); +} +/* Highlighted search terms */ +.algolia-docsearch-suggestion--highlight { + color: lighten($brand-color, 10%); +} +/* Highligted search terms in the main category headers */ +.algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight { + background-color: $brand-color; +} +/* Currently selected suggestion */ +.aa-cursor .algolia-docsearch-suggestion--content { + color: darken($brand-color, 10%); +} +.aa-cursor .algolia-docsearch-suggestion { + background: ligten($brand-color, 30%); +} + +/* For bigger screens, when displaying results in two columns */ +@media (min-width: 768px) { + /* Bottom border of each suggestion */ + .algolia-docsearch-suggestion { + border-bottom-color: lighten($brand-color, 15%); + } + /* Left column, with secondary category header */ + .algolia-docsearch-suggestion--subcategory-column { + border-right-color: lighten($brand-color, 25%); + background-color: lighten($brand-color, 45%); + color: darken($brand-color, 35%); + } +} diff --git a/docs/_sass/_syntax-highlighting.scss b/docs/_sass/_syntax-highlighting.scss new file mode 100755 index 0000000..b1e7faf --- /dev/null +++ b/docs/_sass/_syntax-highlighting.scss @@ -0,0 +1,109 @@ +/** + * Syntax highlighting styles + */ +.highlight { + // markdown editing + $default: #989898; + $bg: #f5f5f5; + $caret: #00bdff; + $black: #000; + $white: #fff; + $invisible: #E0E0E0; + $highlight: #e6e6e6; + $inserted: #DDFFDD; + $output: #7F7F7F; + $promt: #555; + $traceback: #F93232; + $deleted: #fdd; + $selection: #C2E8FF; + $found: #FFE792; + $shadow: #808080; + $comment: #bbbaba; + $invalid: #F9F2CE; + $operator: #626FC9; + $keyword: #7aad36; + $symbol: #E8FFD5; + $type: #6700B9; + $constant: #9870EC; + $var: #4C8FC7; + $attribute: #d42a57; + $function: $keyword; + $built-in: $attribute; + $class: #3A1D72; + $exception: #F93232; + $section: #333333; + $number: $constant; + $literal: #de8325; + $string_re: #699D36; + $tag: $var; + $name-class: #3A77BF; + $entity: #6d98cf; + $punctuation: $black; + + color: $default; + background-color: $bg; + border: 1px solid darken($bg, 5%); + + .bp { color: $caret; } // Name.Builtin.Pseudo + .c { color: $comment; } // Comment + .c1 { @extend .c; } // Comment.Single + .cm { @extend .c; } // Comment.Multiline + .cp { color: $shadow } // Comment.Preproc + .cs { @extend .c; } // Comment.Special + .err { color: $exception; background-color: $invalid } // Error + .gd { color: $black; background-color: $deleted; } // Generic.Deleted + .ge { color: $default; background-color: $highlight; } // Generic.Emph + .gh { color: $section;} // Generic.Heading + .gi { color: $black; background-color: $inserted; } // Generic.Inserted + .go { color: $output } // Generic.Output + .gp { color: $promt } // Generic.Prompt + .gr { color: $exception } // Generic.Error + .gs { background-color: $white; } // Generic.Strong + .gt { color: $traceback } // Generic.Traceback + .gu { color: $black; } // Generic.Subheading + .hll { background-color: $found } + .k { color: $keyword } // Keyword + .kc { color: $constant } // Keyword.Constant + .kd { @extend .k; } // Keyword.Declaration + .kn { @extend .k; } // Keyword.Namespace + .kp { @extend .k; } // Keyword.Pseudo + .kr { @extend .k; } // Keyword.Reserved + .kt { color: $type } // Keyword.Type + .m { color: $number; } // Literal.Number + .mf { @extend .m; } // Literal.Number.Float + .mh { @extend .m; } // Literal.Number.Hex + .mi { @extend .m; } // Literal.Number.Integer + .mo { @extend .m; } // Literal.Number.Oct + .il { @extend .m; } // Literal.Number.Integer.Long + .n { color: $default } // Name + .na { color: $attribute } // Name.Attribute + .nb { color: $built-in } // Name.Builtin + .nc { color: $name-class; } // Name.Class + .nd { color: $shadow } // Name.Decorator + .nf { color: $function } // Name.Function + .ni { color: $entity;} // Name.Entity + .nn { color: $class; text-decoration: underline } // Name.Namespace + .no { color: $constant } // Name.Constant + .nt { color: $tag;} // Name.Tag + .nv { @extend .v; } // Name.Variable + .nx { color: $default; } + .o { color: $punctuation } // Operator.Word + .ow { color: $operator } // Operator.Word + .s { color: $literal } // Literal.String + .s1 { @extend .s; } // Literal.String.Single + .s2 { @extend .s; } // Literal.String.Double + .sb { @extend .s; } // Literal.String.Backtick + .sc { @extend .s; } // Literal.String.Char + .sd { @extend .s; } // Literal.String.Doc + .se { @extend .s; } // Literal.String.Escape + .sh { @extend .s; } // Literal.String.Heredoc + .si { @extend .s; } // Literal.String.Interpol + .sr { color: $string_re; } // Literal.String.Regex + .ss { color: $caret; } // Literal.String.Symbol + .sx { @extend .s; } // Literal.String.Other + .v { color: $var } + .vc { color: $class; } // Name.Variable.Class + .vg { @extend .v; } // Name.Variable.Global + .vi { @extend .v; } // Name.Variable.Instance + .w { color: $invisible; } // Text.Whitespace +} diff --git a/docs/bower.json b/docs/bower.json new file mode 100755 index 0000000..1c7a59c --- /dev/null +++ b/docs/bower.json @@ -0,0 +1,22 @@ +{ + "name": "Spout", + "version": "0.0.1", + "authors": [ + "Adrien Loison