diff --git a/README.md b/README.md
index 5903151..b7bd3f3 100644
--- a/README.md
+++ b/README.md
@@ -38,13 +38,14 @@ saged($i); // alias for sage();die;
sage(1); // shortcut for dumping trace
```
-| Function | Shorthand | |
-|-----------|----------------|-------------------|
-| `sage` | `s` / `d` | Dump |
-| `saged` | `sd` | Dump & die |
-| `ssage` | `ss` | Simple dump |
-| `ssaged` | `ssd` | Simple dump & die |
-| `sage(1)` | `s(1)`/`sd(1)` | Debug backtrace |
+| Function | Shorthand | |
+|-------------|-----------|--------------------------------------------------|
+| `sage` | `s` | Dump (same as `\Sage::dump()`) |
+| `saged` | `sd` | Dump & die |
+| `ssage` | `ss` | Simple dump |
+| `ssaged` | `ssd` | Simple dump & die |
+| `sagetrace` | `s(1)` | Debug backtrace (same as `\Sage::trace()`) |
+| --- | `s(2)` | Backtrace without the arguments - just the paths |
### Simple dump:
@@ -56,13 +57,20 @@ sage(1); // shortcut for dumping trace
### More cool stuff π€―
-To output plain-text mode (no styling **AT ALL**) prefix with `~`. To return instead of echoing, prefix with `@`:
+Sage determines the **passed variable name** and as a side effect can detect all sort of prefixes to the call. Use it
+for some common on-the-fly adjustments to the dump output.
+
+Examples:
```php
-~s($var); // outputs plain text
-$output = @ss(); // returns output
+~ss($var); // outputs plain text
+$output = @ss($var); // returns output instead of displaying it
+print sd($var); // saves output into "sage.html" in the current directory
++sage($var); // ignores depth limit for large objects
```
+See [Advanced section](#-advanced-tips--tricks) below for more tricks.
+
### Verbose versions
If you want to use Sage as part of permanent code (e.g. part of a test helper/logger/exception reporter etc), you can
@@ -295,6 +303,7 @@ ss($GLOBALS, $_SERVER);
// show a trace
Sage::trace();
s(1); // shorthand works too!
+s(2); // trace - but just the paths
Sage::dump( debug_backtrace() ); // you can even pass a custom result from debug_trace and it will be recognized
// dump and die debugging
@@ -327,15 +336,16 @@ sd('Get off my lawn!'); // no effect
For customization instructions read the section below.
* If a variable is an object, its classname can be clicked to open the class in your IDE.
-* There are a couple of real-time modifiers you can use:
- * `~s($var)` this call will output in plain text format.
- * `+s($var)` will disregard depth level limits and output everything (careful, this can hang your browser on huge
- objects)
- * `!s($var)` will show uncollapsed rich output.
- * `-s($var)` will attempt to `ob_clean` the previous output - useful when Sage is obscured by already present HTML.
-
- [Here's a little bit](https://stackoverflow.com/a/69890023/179104) on how it works.
-
+* There are several real-time prefix modifiers you can use (combinations possible):
+
+ | Prefix | | Example |
+ |--------|----------------------------------------------|--------------|
+ | print | Puts output into current DIR as sage.html | print sage() |
+ | + | Dump ignoring depth limits for large objects | + sage() |
+ | ~ | Simplifies sage output (rich->html->plain) | ~ sage() |
+ | - | Clean up any output before dumping | - sage() |
+ | ! | Expand all nodes (in rich view) | ! sage() |
+ | @ | Return output instead of displaying it | @ sage() |
* Sage also includes a naΓ―ve profiler you may find handy. It's for determining relatively which code blocks take longer
than others:
diff --git a/Sage.php b/Sage.php
index cb167ba..368cf01 100644
--- a/Sage.php
+++ b/Sage.php
@@ -45,6 +45,7 @@ class Sage
{
private static $_initialized = false;
private static $_enabledMode = true;
+ private static $_openedFile;
/*
* βββββββ βββββββ ββββ ββββββββββββββ βββββββ βββ ββββββββββ ββββββ ββββββββββββ βββββββ ββββ βββ
@@ -61,22 +62,22 @@ class Sage
* @var string makes visible source file paths clickable to open your editor.
*
* Pre-defined values:
- * 'sublime' => 'subl://open?url=file://%file&line=%line',
- * 'textmate' => 'txmt://open?url=file://%file&line=%line',
- * 'emacs' => 'emacs://open?url=file://%file&line=%line',
- * 'macvim' => 'mvim://open/?url=file://%file&line=%line',
- * 'phpstorm' => 'phpstorm://open?file=%file&line=%line',
- * 'phpstorm-plugin' => 'http://localhost:63342/api/file/%file:%line',
- * 'idea' => 'idea://open?file=%file&line=%line',
- * 'vscode' => 'vscode://file/%file:%line',
- * 'vscode-insiders' => 'vscode-insiders://file/%file:%line',
- * 'vscode-remote' => 'vscode://vscode-remote/%file:%line',
- * 'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%file:%line',
- * 'vscodium' => 'vscodium://file/%file:%line',
- * 'atom' => 'atom://core/open/file?filename=%file&line=%line',
- * 'nova' => 'nova://core/open/file?filename=%file&line=%line',
- * 'netbeans' => 'netbeans://open/?f=%file:%line',
- * 'xdebug' => 'xdebug://%file@%line'
+ * 'sublime' => 'subl://open?url=file://%file&line=%line',
+ * 'textmate' => 'txmt://open?url=file://%file&line=%line',
+ * 'emacs' => 'emacs://open?url=file://%file&line=%line',
+ * 'macvim' => 'mvim://open/?url=file://%file&line=%line',
+ * 'phpstorm' => 'phpstorm://open?file=%file&line=%line',
+ * 'phpstorm-plugin' => 'http://localhost:63342/api/file/%file:%line',
+ * 'idea' => 'idea://open?file=%file&line=%line',
+ * 'vscode' => 'vscode://file/%file:%line',
+ * 'vscode-insiders' => 'vscode-insiders://file/%file:%line',
+ * 'vscode-remote' => 'vscode://vscode-remote/%file:%line',
+ * 'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%file:%line',
+ * 'vscodium' => 'vscodium://file/%file:%line',
+ * 'atom' => 'atom://core/open/file?filename=%file&line=%line',
+ * 'nova' => 'nova://core/open/file?filename=%file&line=%line',
+ * 'netbeans' => 'netbeans://open/?f=%file:%line',
+ * 'xdebug' => 'xdebug://%file@%line'
*
* Or pass a custom string where %fileileileileileile should be replaced with full file path, %line with line number
* to create a custom link. Set to null to disable linking.
@@ -173,7 +174,7 @@ class Sage
* Default:
* array(
* 'UTF-8',
- * 'Windows-1252', // Western; includes iso-8859-1, replace this with windows-1251 if you have Russian code
+ * 'Windows-1252', // Western; includes iso-8859-1, replace this with windows-1251 if you use Russian
* 'euc-jp', // Japanese
* );
*/
@@ -187,12 +188,20 @@ class Sage
*/
public static $returnOutput;
- /**`
+ /**
+ * @var string Write output to this file instead of echoing it. If it ends in `.html` forces output in html mode.
+ *
+ * Default:
+ * false
+ */
+ public static $outputFile;
+
+ /**
* @var array Add new custom Sage wrapper names. Needed for nice backtraces, variable name detection and modifiers.
*
* [!] Use notation `Class::method` for methods.
*
- * Example :
+ * Example:
* function doom_dump($args)
* {
* echo "DOOOM!";
@@ -274,7 +283,9 @@ public static function enabled($forceMode = null)
*/
/**
- * Prints a debug backtrace, same as Sage::dump(1)
+ * Prints a debug backtrace, same as `sage(1)`.
+ *
+ * Skip trace arguments and only see the paths - `sage(2)`
*
* @param array $trace [OPTIONAL] you can pass your own trace, otherwise, `debug_backtrace` will be called
*
@@ -294,35 +305,27 @@ public static function trace($trace = null)
}
/**
- * Dump information about variables, accepts any number of parameters, supports modifiers:
- *
- * clean up any output before Sage and place the dump at the top of page:
- * - Sage::dump()
- * *****
- * expand all nodes on display:
- * ! Sage::dump()
- * *****
- * dump variables disregarding their depth:
- * + Sage::dump()
- * *****
- * return output instead of displaying it:
- * @ Sage::dump()
- * *****
- * force output as plain text
- * ~ Sage::dump()
- *
- * Modifiers are supported by all dump wrapper functions, including Sage::trace(). Space is optional.
- *
- *
- * You can also use the following shorthand to display debug_backtrace():
- * Sage::dump( 1 );
+ * Dump information about variables, accepts any number of parameters, supports prefix-modifiers:
*
- * Passing the result from debug_backtrace() to Sage::dump() as a single parameter will display it as trace too:
- * $trace = debug_backtrace( true );
- * Sage::dump( $trace );
- * Or simply:
- * Sage::dump( debug_backtrace() );
+ * ```
+ * |-------|----------------------------------------------|
+ * | | Example: `+ saged('magic');` |
+ * |-------|----------------------------------------------|
+ * | + | Dump ignoring depth limits for large objects |
+ * | print | Puts output into current DIR as sage.html |
+ * | ~ | Simplifies sage output (rich->html->plain) |
+ * | - | Clean up any output before dumping |
+ * | ! | Expand all nodes (in rich view) |
+ * | @ | Return output instead of displaying it |
+ * |-------|----------------------------------------------|
+ * ```
*
+ * Modifiers are supported by all dump wrapper functions, including Sage::trace(). Combinations possible.
+ *
+ * -----
+ * Shorthand to display debug_backtrace():
+ * Sage::dump( 1 );
+ * Sage::dump( debug_backtrace() ); // must be single parameter!
*
* @param mixed $data
*
@@ -358,9 +361,13 @@ public static function dump($data = null)
self::MODE_CLI,
self::MODE_PLAIN
), true)) {
- $newMode = (PHP_SAPI === 'cli' && self::$cliDetection === true)
- ? self::MODE_CLI
- : self::MODE_RICH;
+ if (self::$outputFile && substr(self::$outputFile, -5) === '.html') {
+ $newMode = self::MODE_RICH;
+ } else {
+ $newMode = (PHP_SAPI === 'cli' && self::$cliDetection === true)
+ ? self::MODE_CLI
+ : self::MODE_RICH;
+ }
self::enabled($newMode);
}
@@ -413,41 +420,94 @@ public static function dump($data = null)
}
}
+ if (! empty($modifiers) && strpos($modifiers, 'print') !== false && isset($callee['file'])) {
+ self::enabled(Sage::MODE_RICH);
+ $outputFileOldValue = self::$outputFile;
+ self::$outputFile = dirname($callee['file']) . '/sage.html';
+ $decorator = 'SageDecoratorsRich';
+ }
+
+ if (self::$outputFile && ! isset(self::$_openedFile[self::$outputFile])) {
+ $firstRunOldValue = $decorator::$firstRun;
+ $decorator::$firstRun = true;
+ }
+
$output = '';
if ($decorator::$firstRun) {
$output .= call_user_func(array($decorator, 'init'));
}
- $trace = false;
- if ($data === 1 && $names === array(null) && func_num_args() === 1) { // Sage::dump(1) shorthand
- $trace = SageHelper::php53orLater() ? debug_backtrace(true) : debug_backtrace();
+ $trace = false;
+ $lightTrace = false;
+ if ($names === array(null) && func_num_args() === 1) {
+ if ($data === 1) {
+ // Sage::dump(1) shorthand
+ $trace = SageHelper::php53orLater() ? debug_backtrace(true) : debug_backtrace();
+ } elseif ($data === 2) {
+ // Sage::dump(2) shorthand todo: create Sage::traceWithoutArgs()
+ $lightTrace = true;
+ $trace = debug_backtrace();
+ }
} elseif (func_num_args() === 1 && is_array($data)) {
$trace = $data; // test if the single parameter is result of debug_backtrace()
}
- $trace and $trace = self::_parseTrace($trace);
+
+ if ($trace) {
+ $trace = self::_parseTrace($trace);
+ }
$output .= call_user_func(array($decorator, 'wrapStart'));
+
if ($trace) {
- $output .= call_user_func(array($decorator, 'decorateTrace'), $trace);
+ $output .= call_user_func(array($decorator, 'decorateTrace'), $trace, $lightTrace);
} else {
- $data = func_num_args() === 0
- ? array('[[no arguments passed]]')
- : func_get_args();
-
- foreach ($data as $k => $argument) {
+ if (func_num_args() === 0) {
SageParser::reset();
- // when the dump arguments take long to generate output, user might have changed the file and
- // Sage might not parse the arguments correctly, so check if names are set and while the
- // displayed names might be wrong, at least don't throw an error
+ $tmp = microtime();
+ $varData = SageParser::process($tmp, '');
+ $varData->type = null;
+ $varData->name = 'Sage called with no arguments';
+ $varData->value = null;
+ $varData->size = null;
+ if (! empty($callee['function'])) {
+ if (! empty($callee['class']) && ! empty($callee['type'])) {
+ $name = $callee['class'] . $callee['type'] . $callee['function'];
+ } else {
+ $name = $callee['function'];
+ }
+ $varData->name = $name . '( no parameters )';
+ }
$output .= call_user_func(
array($decorator, 'decorate'),
- SageParser::process($argument, isset($names[$k]) ? $names[$k] : '')
+ $varData
);
+ } else {
+ foreach (func_get_args() as $k => $argument) {
+ SageParser::reset();
+ // when the dump arguments take long to generate output, user might have changed the file and
+ // Sage might not parse the arguments correctly, so check if names are set and while the
+ // displayed names might be wrong, at least don't throw an error
+ $output .= call_user_func(
+ array($decorator, 'decorate'),
+ SageParser::process($argument, isset($names[$k]) ? $names[$k] : '')
+ );
+ }
}
}
$output .= call_user_func(array($decorator, 'wrapEnd'), $callee, $miniTrace, $previousCaller);
+ // now restore all on-the-fly settings and return
+
+ if (self::$outputFile) {
+ if (! isset(self::$_openedFile[self::$outputFile])) {
+ self::$_openedFile[self::$outputFile] = fopen(self::$outputFile, 'w');
+ $decorator::$firstRun = $firstRunOldValue;
+ }
+
+ fwrite(self::$_openedFile[self::$outputFile], $output);
+ }
+
self::enabled($enabledMode);
$decorator::$firstRun = false;
@@ -470,12 +530,22 @@ public static function dump($data = null)
return $output;
}
+ if (! empty($modifiers) && strpos($modifiers, 'print') !== false && isset($callee['file'])) {
+ $tmp = self::$outputFile;
+ self::$outputFile = $outputFileOldValue;
+
+ return 'Sage -> ' . $tmp . PHP_EOL;
+ }
}
if (self::$returnOutput) {
return $output;
}
+ if (self::$outputFile) {
+ return 5463;
+ }
+
echo $output;
return 5463;
@@ -611,7 +681,7 @@ private static function _getCalleeInfo($trace)
[\x07{(]
# search for modifiers (group 1)
- ([-+!@~]*)?
+ ([-+!@~]|print*)?
# spaces
\x07*
@@ -686,7 +756,7 @@ private static function _getCalleeInfo($trace)
}
// replace whatever was inside quotes or brackets with untypeable characters, we don't
- // need that info. We'll later replace the whole string with '...'
+ // need that info.
if ($inBrackets > 0) {
if ($inBrackets > 1 || $letter !== $openedBracket) {
$paramsString[$i] = "\x07";
@@ -703,11 +773,11 @@ private static function _getCalleeInfo($trace)
}
// by now we have an un-nested arguments list, lets make it to an array for processing further
- $arguments = explode(',', preg_replace("[\x07+]", '...', $paramsString));
+ $arguments = explode(',', preg_replace("[\x07+]", "\x07", $paramsString));
// test each argument whether it was passed literary or was it an expression or a variable name
$parameters = array();
- $blacklist = array('null', 'true', 'false', 'array(...)', 'array()', '"..."', '[...]', 'b"..."',);
+ $blacklist = array('null', 'true', 'false', "array(\x07)", 'array()', "\"\x07\"", '[\x07]', 'b\"\x07\"',);
foreach ($arguments as $argument) {
$argument = trim($argument);
@@ -939,7 +1009,9 @@ private static function _init()
self::_initSetting('expandedByDefault', false);
self::_initSetting('cliDetection', true);
self::_initSetting('cliColors', true);
- self::_initSetting('charEncodings', array(
+ self::_initSetting(
+ 'charEncodings',
+ array(
'UTF-8',
'Windows-1252', // Western; includes iso-8859-1, replace this with windows-1251 if you have Russian code
'euc-jp', // Japanese
diff --git a/decorators/SageDecoratorsPlain.php b/decorators/SageDecoratorsPlain.php
index 7ac1805..e6ee256 100644
--- a/decorators/SageDecoratorsPlain.php
+++ b/decorators/SageDecoratorsPlain.php
@@ -49,13 +49,13 @@ public static function decorate(SageVariableData $varData, $level = 0)
return $output;
}
- public static function decorateTrace($traceData)
+ public static function decorateTrace($traceData, $pathsOnly = false)
{
// if we're dealing with a framework stack, lets verbosely display last few steps only, and not hang the browser
$optimizeOutput = count($traceData) >= 10 && Sage::$maxLevels !== false;
$maxLevels = Sage::$maxLevels;
- $output = self::_title('TRACE');
+ $output = self::_title($pathsOnly ? 'QUICK TRACE' : 'TRACE');
$lastStep = count($traceData);
foreach ($traceData as $stepNo => $step) {
if ($optimizeOutput) {
@@ -72,7 +72,7 @@ public static function decorateTrace($traceData)
? SageHelper::ideLink($step['file'], $step['line'])
: 'PHP internal call'
),
- 'title'
+ 'header'
);
$appendDollar = $step['function'] === '{closure}' ? '' : '$';
@@ -85,16 +85,17 @@ public static function decorateTrace($traceData)
$output .= ')';
} else {
$output .= $appendDollar . implode(', ' . $appendDollar, array_keys($step['args'])) . ')';
- $output .= PHP_EOL . self::_colorize(
- ' ' . str_repeat('β', 27) . ' Arguments ' . str_repeat('β', 38),
- 'title'
- );
}
}
$output .= PHP_EOL;
}
- if (! empty($step['args'])) {
+ if (! $pathsOnly && ! empty($step['args'])) {
+ $output .= self::_colorize(
+ ' β' . str_repeat('β', 26) . ' Arguments ' . str_repeat('β', 37) . 'β',
+ 'header'
+ );
+
$i = 0;
foreach ($step['args'] as $name => $argument) {
$argument = SageParser::process(
@@ -111,30 +112,33 @@ public static function decorateTrace($traceData)
Sage::$maxLevels = $maxLevels;
}
}
- $output .= ' )' . PHP_EOL;
+
+ $output .= ' ' . self::_colorize('β' . str_repeat('β', 74) . 'β', 'header');
}
- if (! empty($step['object'])) {
+ if (! $pathsOnly && ! empty($step['object'])) {
$output .= self::_colorize(
- ' ' . str_repeat('β', 27) . ' Callee object ' . str_repeat('β', 34),
- 'title'
+ ' β' . str_repeat('β', 26) . ' Callee object ' . str_repeat('β', 33) . 'β',
+ 'header'
);
$maxLevels = Sage::$maxLevels;
if ($maxLevels) {
// in cli the terminal window is filled too quickly to display huge objects
Sage::$maxLevels = Sage::enabled() === Sage::MODE_CLI
- ? 1
+ ? 2
: $maxLevels + 1;
}
- $output .= self::decorate(SageParser::process($step['object']), 1);
+ $output .= self::decorate(SageParser::process($step['object']), 2);
if ($maxLevels) {
Sage::$maxLevels = $maxLevels;
}
+
+ $output .= ' ' . self::_colorize('β' . str_repeat('β', 74) . 'β', 'header');
}
if ($stepNo !== $lastStep) {
- $output .= self::_colorize(str_repeat('β', 80), 'title');
+ $output .= self::_colorize(str_repeat('β', 80), 'header');
}
}
@@ -163,8 +167,8 @@ private static function _colorize($text, $type, $nlAfter = true)
case 'type':
$text = "{$text}";
break;
- case 'title':
- $text = "{$text}";
+ case 'header':
+ $text = "";
break;
}
@@ -177,7 +181,7 @@ private static function _colorize($text, $type, $nlAfter = true)
$optionsMap = array(
'key' => "\x1b[33m", // yellow
- 'title' => "\x1b[36m", // cyan
+ 'header' => "\x1b[36m", // cyan
'type' => "\x1b[35;1m", // magenta bold
'value' => "\x1b[32m", // green
);
@@ -196,16 +200,13 @@ private static function _title($text)
$escaped = SageHelper::esc($text);
$lengthDifference = strlen($escaped) - strlen($text);
- $ret = self::_colorize('β' . str_repeat('β', 78) . 'β' . PHP_EOL, 'title', false);
+ $ret = 'β' . str_repeat('β', 78) . 'β' . PHP_EOL;
if ($text) {
- $ret .= self::_colorize(
- 'β' . str_pad($escaped, 78 + $lengthDifference, ' ', STR_PAD_BOTH) . 'β' . PHP_EOL,
- 'title',
- false
- );
+ $ret .= 'β' . str_pad($escaped, 78 + $lengthDifference, ' ', STR_PAD_BOTH) . 'β' . PHP_EOL;
}
+ $ret .= 'β' . str_repeat('β', 78) . 'β';
- return $ret . self::_colorize('β' . str_repeat('β', 78) . 'β', 'title');
+ return self::_colorize($ret, 'header');
}
public static function wrapStart()
@@ -219,7 +220,7 @@ public static function wrapStart()
public static function wrapEnd($callee, $miniTrace, $prevCaller)
{
- $lastLine = self::_colorize(str_repeat('β', 80), 'title');
+ $lastLine = self::_colorize(str_repeat('β', 80), 'header');
$isHtml = Sage::enabled() === Sage::MODE_PLAIN;
$lastChar = $isHtml ? '' : '';
$traceDisplay = '';
@@ -245,7 +246,7 @@ public static function wrapEnd($callee, $miniTrace, $prevCaller)
return $lastLine
. self::_colorize(
'Call stack ' . SageHelper::ideLink($callee['file'], $callee['line']) . $traceDisplay,
- 'title'
+ 'header'
)
. $lastChar;
}
@@ -302,8 +303,7 @@ function_exists('sapi_windows_vt100_support')
}
return <<<'HTML'
-
+
HTML;
}
}
diff --git a/decorators/SageDecoratorsRich.php b/decorators/SageDecoratorsRich.php
index d54d012..de23764 100644
--- a/decorators/SageDecoratorsRich.php
+++ b/decorators/SageDecoratorsRich.php
@@ -74,7 +74,7 @@ public static function decorate(SageVariableData $varData)
return $output;
}
- public static function decorateTrace($traceData)
+ public static function decorateTrace($traceData, $namesOnly = false)
{
// if we're dealing with a framework stack, lets verbosely display last few steps only, and not hang the browser
$optimizeOutput = count($traceData) >= 10 && Sage::$maxLevels !== false;
@@ -123,12 +123,12 @@ public static function decorateTrace($traceData)
$firstTab = '';
}
- if (! empty($step['args'])) {
+ if (! $namesOnly && ! empty($step['args'])) {
$output .= "
Arguments";
$firstTab = '';
}
- if (! empty($step['object'])) {
+ if (! $namesOnly && ! empty($step['object'])) {
SageParser::reset();
$calleeDump = SageParser::process($step['object']);
@@ -142,7 +142,7 @@ public static function decorateTrace($traceData)
$output .= "{$step['source']}
";
}
- if (! empty($step['args'])) {
+ if (! $namesOnly && ! empty($step['args'])) {
$output .= '';
foreach ($step['args'] as $k => $arg) {
SageParser::reset();
@@ -151,7 +151,7 @@ public static function decorateTrace($traceData)
$output .= '';
}
- if (! empty($step['object'])) {
+ if (! $namesOnly && ! empty($step['object'])) {
$output .= '' . self::decorate($calleeDump) . '';
}
diff --git a/inc/shorthands.inc.php b/inc/shorthands.inc.php
index d4b612e..c69f87d 100644
--- a/inc/shorthands.inc.php
+++ b/inc/shorthands.inc.php
@@ -8,21 +8,44 @@
* βββββββββββ βββββββββββββββ βββ βββ βββ ββββββ ββββββ ββββββββββββββββββββββ
* βββββββββββ βββ βββββββ βββ βββ βββ βββ ββββββ ββββββ ββββββββββββ ββββββββ
*
- * |----------|-----------|-------------------|
- * | Function | Shorthand | |
- * |----------|-----------|-------------------|
- * | `sage` | `s` | Dump |
- * | `saged` | `sd` | Dump & die |
- * | `ssage` | `ss` | Simple dump |
- * | `ssaged` | `ssd` | Simple dump & die |
- * |----------|-----------|-------------------|
+ * |-------------|-----------|--------------------------------------------------|
+ * | Function | Shorthand | |
+ * |-------------|-----------|--------------------------------------------------|
+ * | `sage` | `s` | Dump (same as `\Sage::dump()`) |
+ * | `saged` | `sd` | Dump & die |
+ * | `ssage` | `ss` | Simple dump |
+ * | `ssaged` | `ssd` | Simple dump & die |
+ * | `sagetrace` | `s(1)` | Debug backtrace (same as `\Sage::trace()`) |
+ * | --- | `s(2)` | Backtrace without the arguments - just the paths |
+ * |-------------|-----------|--------------------------------------------------|
+ *
+ * ββββ ββββ βββββββ βββββββ βββββββββββββββββββββββββββββ ββββββββ
+ * βββββ ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ * ββββββββββββββ ββββββ ββββββββββββ βββββββββ ββββββββββββββββ
+ * ββββββββββββββ ββββββ ββββββββββββ βββββββββ ββββββββββββββββ
+ * βββ βββ ββββββββββββββββββββββββββ ββββββββββββββ βββββββββββ
+ * βββ βββ βββββββ βββββββ ββββββ ββββββββββββββ βββββββββββ
+ *
+ * |-------|----------------------------------------------|
+ * | | Example: `+ saged('magic');` |
+ * |-------|----------------------------------------------|
+ * | + | Dump ignoring depth limits for large objects |
+ * | print | Puts output into current DIR as sage.html |
+ * | ~ | Simplifies sage output (rich->html->plain) |
+ * | - | Clean up any output before dumping |
+ * | ! | Expand all nodes (in rich view) |
+ * | @ | Return output instead of displaying it |
+ * |-------|----------------------------------------------|
+ *
*/
if (! function_exists('sage')) {
/**
* Alias of Sage::dump()
*
- * @return string|int @see Sage::dump()
+ * @return string|int
+ *
+ * @see Sage::dump()
*/
function sage()
{
@@ -42,7 +65,9 @@ function sage()
/**
* Alias of Sage::dump()
*
- * @return string|int @see Sage::dump()
+ * @return string|int
+ *
+ * @see Sage::dump()
*/
function s()
{
@@ -245,3 +270,23 @@ function d()
return call_user_func_array(array('Sage', 'dump'), $params);
}
}
+
+if (! function_exists('sagetrace')) {
+ /**
+ * Alias of Sage::dump()
+ *
+ * Same as sage(), here just to allow drop-in replacement for Kint.
+ *
+ * @return string|int @see Sage::dump()
+ */
+ function sagetrace()
+ {
+ if (! Sage::enabled()) {
+ return 5463;
+ }
+
+ Sage::$aliases[] = __FUNCTION__;
+
+ return Sage::trace();
+ }
+}
diff --git a/parsers/SageParsersMicrotime.php b/parsers/SageParsersMicrotime.php
index 1d9fc05..0bd14fb 100644
--- a/parsers/SageParsersMicrotime.php
+++ b/parsers/SageParsersMicrotime.php
@@ -39,7 +39,7 @@ protected static function parse(&$variable, $varData)
}
if (SageHelper::isRichMode()) {
- $tabContents = "SINCE LAST CALL: " . round($lap, 4) . 's.';
+ $tabContents = "SINCE LAST SUCH CALL: " . round($lap, 4) . 's.';
if ($numberOfCalls > 1) {
$tabContents .= "\nSINCE START: {$sinceStart}";
$tabContents .= "\nAVERAGE DURATION: {$averageDuration}";
@@ -49,7 +49,7 @@ protected static function parse(&$variable, $varData)
$varData->addTabToView($variable, 'Benchmark', $tabContents);
} else {
$varData->extendedValue = array(
- 'Since last call' => $sinceLast
+ 'Since last such call' => $sinceLast
);
if ($sinceStart !== null) {
diff --git a/resources/compiled/aante-light.css b/resources/compiled/aante-light.css
index 86a7e9d..c3df76b 100644
--- a/resources/compiled/aante-light.css
+++ b/resources/compiled/aante-light.css
@@ -1 +1 @@
-._sage::selection{background:#aaa;color:#1d1e1e}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#aaa}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAYAAAC5OOBJAAAAvklEQVR42mNgGMFAS0uLLSQk5HxoaOh/XDg4OLgdpwEBAQEGQAN+YtMIFH/i4ODAg9cFQNMbsWkOCgrKJMv5ID5Qipko/6M7PzAw0ImkAIQ5H0hvISv0gZpP+fn5qZAVfcBAkmEYBaNZcjRLjmbJUUCvqAIlDlAiASUWkjWDkiU0eTaSpBGUEZBy1E9QRiFWLzO2LEmU80GZHkcRhN/5oGIGVNzgKIbwOx9UwOErAIl2/igYzZKjWXI0S9IHAAASJijo0Ypj8AAAAABJRU5ErkJggg==") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #d7d7d7}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#06f;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:red}._sage dfn{font-style:normal;font-weight:normal;color:#1d1e1e}._sage pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#aaa}._sage ._sage-popup-trigger:hover{color:#d7d7d7}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#1d1e1e;text-shadow:none}._sage a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #d7d7d7}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}._sage ul._sage-tabs li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#aaa;color:red}._sage ul._sage-tabs li._sage-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#aaa;color:red}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}._sage-report td{background:#f8f8f8;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}._sage-report tr:hover var{color:red}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #06f}._sage-trace ._sage-source ._sage-highlight{background:#f8f8f8}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#1d1e1e}._sage-trace ._sage-parent>var>a{color:#06f}._sage-focused{box-shadow:0 0 3px 2px red}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}._sage dt{font-weight:normal}._sage dt._sage-parent{margin-top:4px}._sage>dl{background:linear-gradient(90deg, rgba(255, 255, 255, 0) 0, #fff 15px)}._sage dl dl{margin-top:4px;padding-left:25px;border-left:none}._sage>dl>dt{background:#f8f8f8}._sage ul{margin:0;padding-left:0}._sage ul:not(._sage-tabs)>li{border-left:0}._sage ul._sage-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}._sage ul._sage-tabs li,._sage ul._sage-tabs li+li{margin:0 0 0 4px}._sage ul._sage-tabs li{border-bottom-width:0;height:25px}._sage ul._sage-tabs li:first-child{margin-left:0}._sage ul._sage-tabs li._sage-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}._sage ul._sage-tabs li._sage-active-tab:hover{border-bottom:1px solid #fff}._sage ul>li>pre{border:1px solid #d7d7d7}._sage dt:hover+dd>ul{border-color:#aaa}._sage pre{background:#fff;margin-top:4px;margin-left:25px}._sage ._sage-popup-trigger:hover{color:red}._sage ._sage-source ._sage-highlight{background:#cfc}._sage-report td{background:#fff}._sage-report td>dl{padding:0;margin:0}._sage-report td>dl>dt._sage-parent{margin:0}._sage-report td:first-child,._sage-report td,._sage-report th{padding:2px 4px}._sage-report td._sage-empty{background:#d7d7d7 !important}._sage-report dd,._sage-report dt{background:#fff}._sage-report tr:hover>td{box-shadow:none;background:#cfc}
+._sage::selection{background:#aaa;color:#1d1e1e}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#f8f8f8;border:1px solid #d7d7d7;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#aaa}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAYAAAC5OOBJAAAAvklEQVR42mNgGMFAS0uLLSQk5HxoaOh/XDg4OLgdpwEBAQEGQAN+YtMIFH/i4ODAg9cFQNMbsWkOCgrKJMv5ID5Qipko/6M7PzAw0ImkAIQ5H0hvISv0gZpP+fn5qZAVfcBAkmEYBaNZcjRLjmbJUUCvqAIlDlAiASUWkjWDkiU0eTaSpBGUEZBy1E9QRiFWLzO2LEmU80GZHkcRhN/5oGIGVNzgKIbwOx9UwOErAIl2/igYzZKjWXI0S9IHAAASJijo0Ypj8AAAAABJRU5ErkJggg==") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent{cursor:pointer}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #d7d7d7}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#06f;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:red}._sage dfn{font-style:normal;font-weight:normal;color:#1d1e1e}._sage pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #d7d7d7;background:#f8f8f8;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#aaa}._sage ._sage-popup-trigger:hover{color:#d7d7d7}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#1d1e1e;text-shadow:none}._sage a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #d7d7d7}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#f8f8f8;border:1px solid #d7d7d7;border-top:0}._sage ul._sage-tabs li{background:#f8f8f8;border:1px solid #d7d7d7;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#aaa;color:red}._sage ul._sage-tabs li._sage-active-tab{background:#f8f8f8;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#aaa;color:red}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #d7d7d7;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#f8f8f8;color:#1d1e1e}._sage-report td{background:#f8f8f8;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #aaa inset}._sage-report tr:hover var{color:red}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #06f}._sage-trace ._sage-source ._sage-highlight{background:#f8f8f8}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#1d1e1e}._sage-trace ._sage-parent>var>a{color:#06f}._sage-focused{box-shadow:0 0 3px 2px red}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}._sage dt{font-weight:normal}._sage dt._sage-parent{margin-top:4px}._sage>dl{background:linear-gradient(90deg, rgba(255, 255, 255, 0) 0, #fff 15px)}._sage dl dl{margin-top:4px;padding-left:25px;border-left:none}._sage>dl>dt{background:#f8f8f8}._sage ul{margin:0;padding-left:0}._sage ul:not(._sage-tabs)>li{border-left:0}._sage ul._sage-tabs{background:#f8f8f8;border:1px solid #d7d7d7;border-width:0 1px 1px 1px;padding:4px 0 0 12px;margin-left:-1px;margin-top:-1px}._sage ul._sage-tabs li,._sage ul._sage-tabs li+li{margin:0 0 0 4px}._sage ul._sage-tabs li{border-bottom-width:0;height:25px}._sage ul._sage-tabs li:first-child{margin-left:0}._sage ul._sage-tabs li._sage-active-tab{border-top:1px solid #d7d7d7;background:#fff;font-weight:bold;padding-top:0;border-bottom:1px solid #fff !important;margin-bottom:-1px}._sage ul._sage-tabs li._sage-active-tab:hover{border-bottom:1px solid #fff}._sage ul>li>pre{border:1px solid #d7d7d7}._sage dt:hover+dd>ul{border-color:#aaa}._sage pre{background:#fff;margin-top:4px;margin-left:25px}._sage ._sage-popup-trigger:hover{color:red}._sage ._sage-source ._sage-highlight{background:#cfc}._sage-report td{background:#fff}._sage-report td>dl{padding:0;margin:0}._sage-report td>dl>dt._sage-parent{margin:0}._sage-report td:first-child,._sage-report td,._sage-report th{padding:2px 4px}._sage-report td._sage-empty{background:#d7d7d7 !important}._sage-report dd,._sage-report dt{background:#fff}._sage-report tr:hover>td{box-shadow:none;background:#cfc}
diff --git a/resources/compiled/original.css b/resources/compiled/original.css
index d84622e..b329c8b 100644
--- a/resources/compiled/original.css
+++ b/resources/compiled/original.css
@@ -1 +1 @@
-._sage::selection{background:#0092db;color:#1d1e1e}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#e0eaef;border:1px solid #b6cedb;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#0092db}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAACVBMVEX///82b4tctzBls0NMAAAAQklEQVR42rWRIQ4AAAgCwf8/2qgER2BeuwJsgAqIzekMfMryPL9XQSkobE6vwKcsz/N7FfPvh09lnPf/b+7673+f0uHuAZ/EdkNQAAAAAElFTkSuQmCC") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #b6cedb}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#0092db;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:#5cb730}._sage dfn{font-style:normal;font-weight:normal;color:#1d1e1e}._sage pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#0092db}._sage ._sage-popup-trigger:hover{color:#b6cedb}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#1d1e1e;text-shadow:none}._sage a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #b6cedb}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}._sage ul._sage-tabs li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#0092db;color:#5cb730}._sage ul._sage-tabs li._sage-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#0092db;color:#5cb730}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #b6cedb;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#c1d4df;color:#1d1e1e}._sage-report td{background:#e0eaef;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}._sage-report tr:hover var{color:#5cb730}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #0092db}._sage-trace ._sage-source ._sage-highlight{background:#c1d4df}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#1d1e1e}._sage-trace ._sage-parent>var>a{color:#0092db}._sage-focused{box-shadow:0 0 3px 2px #5cb730}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}._sage>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}._sage ul._sage-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}._sage>dl:not(._sage-trace)>dd>ul._sage-tabs li{background:#e0eaef}._sage>dl:not(._sage-trace)>dd>ul._sage-tabs li._sage-active-tab{background:#c1d4df}._sage>dl._sage-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}._sage ._sage-source ._sage-highlight{background:#f0eb96}
+._sage::selection{background:#0092db;color:#1d1e1e}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#1d1e1e;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#e0eaef;border:1px solid #b6cedb;color:#1d1e1e;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#0092db}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAACVBMVEX///82b4tctzBls0NMAAAAQklEQVR42rWRIQ4AAAgCwf8/2qgER2BeuwJsgAqIzekMfMryPL9XQSkobE6vwKcsz/N7FfPvh09lnPf/b+7673+f0uHuAZ/EdkNQAAAAAElFTkSuQmCC") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent{cursor:pointer}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #b6cedb}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#0092db;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:#5cb730}._sage dfn{font-style:normal;font-weight:normal;color:#1d1e1e}._sage pre{color:#1d1e1e;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#0092db}._sage ._sage-popup-trigger:hover{color:#b6cedb}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#1d1e1e;text-shadow:none}._sage a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #b6cedb}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}._sage ul._sage-tabs li{background:#c1d4df;border:1px solid #b6cedb;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#0092db;color:#5cb730}._sage ul._sage-tabs li._sage-active-tab{background:#e0eaef;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#0092db;color:#5cb730}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #b6cedb;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#c1d4df;color:#1d1e1e}._sage-report td{background:#e0eaef;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}._sage-report tr:hover var{color:#5cb730}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #0092db}._sage-trace ._sage-source ._sage-highlight{background:#c1d4df}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#1d1e1e}._sage-trace ._sage-parent>var>a{color:#0092db}._sage-focused{box-shadow:0 0 3px 2px #5cb730}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}._sage>dl>dt{background:linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%)}._sage ul._sage-tabs{background:linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%)}._sage>dl:not(._sage-trace)>dd>ul._sage-tabs li{background:#e0eaef}._sage>dl:not(._sage-trace)>dd>ul._sage-tabs li._sage-active-tab{background:#c1d4df}._sage>dl._sage-trace>dt{background:linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%)}._sage ._sage-source ._sage-highlight{background:#f0eb96}
diff --git a/resources/compiled/sage.js b/resources/compiled/sage.js
index a9f7f03..d376d1b 100644
--- a/resources/compiled/sage.js
+++ b/resources/compiled/sage.js
@@ -1 +1 @@
-if("undefined"==typeof _sageInitialized){const r={t:[],i:-(_sageInitialized=1),o:function(e){const n=window.getSelection(),t=document.createRange();t.selectNodeContents(e),n.removeAllRanges(),n.addRange(t)},u:function(e,n){Array.prototype.slice.call(document.querySelectorAll(e),0).forEach(n)},l:function(e,n){return!!e.classList&&e.classList.contains(n=void 0===n?"_sage-show":n)},g:function(e,n){e.classList.add(n=void 0===n?"_sage-show":n)},v:function(e,n){return e.classList.remove(n=void 0===n?"_sage-show":n),e},next:function(e){for(;"dd"!==(e=e.nextElementSibling).nodeName.toLowerCase(););return e},toggle:function(e,n){var t=r.next(e);(n=void 0===n?r.l(e):n)?r.v(e):r.g(e),1===t.childNodes.length&&(t=t.childNodes[0].childNodes[0])&&r.l(t,"_sage-parent")&&r.toggle(t,n)},_:function(e,n){const t=r.next(e),i=t.getElementsByClassName("_sage-parent");let o=i.length;for(void 0===n&&(n=r.l(e));o--;)r.toggle(i[o],n);r.toggle(e,n)},p:function(e){var n=document.getElementsByClassName("_sage-parent");let t=n.length;for(var i=r.l(e.parentNode);t--;)r.toggle(n[t],i)},h:function(e){let n,t=e,i=0;for(e.parentNode.getElementsByClassName("_sage-active-tab")[0].className="",e.className="_sage-active-tab";t=t.previousSibling;)1===t.nodeType&&i++;n=e.parentNode.nextSibling.childNodes;for(let e=0;eli:not(._sage-active-tab)",function(e){0===e.offsetWidth&&0===e.offsetHeight||r.t.push(e)})},tag:function(e){return"<"+e+">"},C:function(e){let n;(n=window.open())&&(n.document.open(),n.document.write(r.tag("html")+r.tag("head")+"Sage β― ("+(new Date).toISOString()+")"+r.tag('meta charset="utf-8"')+document.getElementsByClassName("_sage-js")[0].outerHTML+document.getElementsByClassName("_sage-css")[0].outerHTML+r.tag("/head")+r.tag("body")+''+e.parentNode.outerHTML+"
"+r.tag("/body")),n.document.close())},T:function(e,t,n){const i=e.tBodies[0],o=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"}),r=void 0===n.I?1:n.I;n.I=-1*r,[].slice.call(e.tBodies[0].rows).sort(function(e,n){return r*o.compare(e.cells[t].textContent,n.cells[t].textContent)}).forEach(function(e){i.appendChild(e)})},A:{P:function(e){var n="_sage-focused",t=document.querySelector("."+n);if(t&&r.v(t,n),-1!==e){t=r.t[e];r.g(t,n);const i=function(e){return e.offsetTop+(e.offsetParent?i(e.offsetParent):0)};n=i(t)-window.innerHeight/2;window.scrollTo(0,n)}r.i=e},F:function(e,n){return e?--n<0&&(n=r.t.length-1):++n>=r.t.length&&(n=0),r.A.P(n),!1}}};window.addEventListener("click",function(e){let n=e.target,t=n.nodeName.toLowerCase();if(r.m(n)){if("dfn"===t)r.o(n),n=n.parentNode;else if("var"===t)n=n.parentNode,t=n.nodeName.toLowerCase();else if("th"===t)return e.ctrlKey||r.T(n.parentNode.parentNode.parentNode,n.cellIndex,n),!1;if("li"===t&&"_sage-tabs"===n.parentNode.className)return"_sage-active-tab"!==n.className&&(r.h(n),-1!==r.i&&r.k()),!1;if("nav"===t)return"footer"===n.parentNode.nodeName.toLowerCase()?(n=n.parentNode,r.l(n)?r.v(n):r.g(n)):setTimeout(function(){0e&&(t=e),ili:not(._sage-active-tab)",function(e){0===e.offsetWidth&&0===e.offsetHeight||a.t.push(e)})},tag:function(e){return"<"+e+">"},C:function(e){let t;(t=window.open())&&(t.document.open(),t.document.write(a.tag("html")+a.tag("head")+"Sage β― ("+(new Date).toISOString()+")"+a.tag('meta charset="utf-8"')+document.getElementsByClassName("_sage-js")[0].outerHTML+document.getElementsByClassName("_sage-css")[0].outerHTML+a.tag("/head")+a.tag("body")+''+e.parentNode.outerHTML+"
"+a.tag("/body")),t.document.close())},I:function(e,n,t){const i=e.tBodies[0],o=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"}),a=void 0===t.T?1:t.T;t.T=-1*a,[].slice.call(e.tBodies[0].rows).sort(function(e,t){return a*o.compare(e.cells[n].textContent,t.cells[n].textContent)}).forEach(function(e){i.appendChild(e)})},A:{P:function(e){var t="_sage-focused",n=document.querySelector("."+t);if(n&&a.v(n,t),-1!==e){n=a.t[e];a.g(n,t);const i=function(e){return e.offsetTop+(e.offsetParent?i(e.offsetParent):0)};t=i(n)-window.innerHeight/2;window.scrollTo(0,t)}a.i=e},F:function(e,t){return e?--t<0&&(t=a.t.length-1):++t>=a.t.length&&(t=0),a.A.P(t),!1}}};window.addEventListener("click",function(e){let t=e.target,n=t.nodeName.toLowerCase();if(a.m(t)){if("dfn"===n)a.o(t),t=t.parentNode;else if("var"===n)t=t.parentNode,n=t.nodeName.toLowerCase();else if("th"===n)return e.ctrlKey||a.I(t.parentNode.parentNode.parentNode,t.cellIndex,t),!1;if("li"===n&&"_sage-tabs"===t.parentNode.className)return"_sage-active-tab"!==t.className&&(a.h(t),-1!==a.i&&a.k()),!1;if("nav"===n)return"footer"===t.parentNode.nodeName.toLowerCase()?(t=t.parentNode,a.l(t)?a.v(t):a.g(t)):setTimeout(function(){0e&&(n=e),idl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg==") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #586e75}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#268bd2;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:#2aa198}._sage dfn{font-style:normal;font-weight:normal;color:#93a1a1}._sage pre{color:#839496;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#268bd2}._sage ._sage-popup-trigger:hover{color:#586e75}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#839496;text-shadow:none}._sage a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #586e75}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}._sage ul._sage-tabs li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#268bd2;color:#2aa198}._sage ul._sage-tabs li._sage-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#268bd2;color:#2aa198}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #586e75;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#073642;color:#93a1a1}._sage-report td{background:#002b36;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}._sage-report tr:hover var{color:#2aa198}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #268bd2}._sage-trace ._sage-source ._sage-highlight{background:#073642}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#93a1a1}._sage-trace ._sage-parent>var>a{color:#268bd2}._sage-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}body{background:#073642;color:#fff}._sage{background:#073642;box-shadow:0 0 5px 3px #073642}._sage>dl>dt,._sage ul._sage-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}._sage ul._sage-tabs li._sage-active-tab{padding-top:7px;height:34px}
+._sage::selection{background:#268bd2;color:#839496}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#839496;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#002b36;border:1px solid #586e75;color:#839496;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#268bd2}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg==") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent{cursor:pointer}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #586e75}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#268bd2;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:#2aa198}._sage dfn{font-style:normal;font-weight:normal;color:#93a1a1}._sage pre{color:#839496;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#268bd2}._sage ._sage-popup-trigger:hover{color:#586e75}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#839496;text-shadow:none}._sage a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #586e75}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}._sage ul._sage-tabs li{background:#073642;border:1px solid #586e75;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#268bd2;color:#2aa198}._sage ul._sage-tabs li._sage-active-tab{background:#002b36;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#268bd2;color:#2aa198}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #586e75;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#073642;color:#93a1a1}._sage-report td{background:#002b36;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}._sage-report tr:hover var{color:#2aa198}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #268bd2}._sage-trace ._sage-source ._sage-highlight{background:#073642}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#93a1a1}._sage-trace ._sage-parent>var>a{color:#268bd2}._sage-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}body{background:#073642;color:#fff}._sage{background:#073642;box-shadow:0 0 5px 3px #073642}._sage>dl>dt,._sage ul._sage-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}._sage ul._sage-tabs li._sage-active-tab{padding-top:7px;height:34px}
diff --git a/resources/compiled/solarized.css b/resources/compiled/solarized.css
index ada78de..c13ed35 100644
--- a/resources/compiled/solarized.css
+++ b/resources/compiled/solarized.css
@@ -1 +1 @@
-._sage::selection{background:#268bd2;color:#657b83}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#268bd2}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg==") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #93a1a1}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#268bd2;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:#2aa198}._sage dfn{font-style:normal;font-weight:normal;color:#586e75}._sage pre{color:#657b83;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#268bd2}._sage ._sage-popup-trigger:hover{color:#93a1a1}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#657b83;text-shadow:none}._sage a:hover{color:#586e75;border-bottom:1px dotted #586e75}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #93a1a1}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}._sage ul._sage-tabs li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#268bd2;color:#2aa198}._sage ul._sage-tabs li._sage-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#268bd2;color:#2aa198}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #93a1a1;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#eee8d5;color:#586e75}._sage-report td{background:#fdf6e3;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}._sage-report tr:hover var{color:#2aa198}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #268bd2}._sage-trace ._sage-source ._sage-highlight{background:#eee8d5}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#586e75}._sage-trace ._sage-parent>var>a{color:#268bd2}._sage-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}._sage>dl>dt,._sage ul._sage-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}._sage ul._sage-tabs li._sage-active-tab{padding-top:7px;height:34px}
+._sage::selection{background:#268bd2;color:#657b83}._sage,._sage::before,._sage::after,._sage *,._sage *::before,._sage *::after{box-sizing:border-box;border-radius:0;color:#657b83;float:none !important;font-family:ui-monospace,"Cascadia Code","Source Code Pro",Menlo,Consolas,"DejaVu Sans Mono",monospace;line-height:15px;margin:0;padding:0;text-align:left}._sage{font-size:13px;margin:8px 0;overflow-x:auto;white-space:nowrap}._sage u{color:#ff8c00}._sage dt{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;overflow:auto;padding:4px}._sage dt:hover{border-color:#268bd2}._sage>dl dl{padding:0 0 0 12px}._sage nav{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg==") no-repeat scroll 0 0 rgba(0,0,0,0);cursor:pointer;display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle}._sage dt._sage-parent{cursor:pointer}._sage dt._sage-parent:hover nav{background-position:0 -15px}._sage dt._sage-parent._sage-show:hover>nav{background-position:0 -45px}._sage dt._sage-show>nav{background-position:0 -30px}._sage dt._sage-parent+dd{display:none;border-left:1px dashed #93a1a1}._sage dt._sage-parent._sage-show+dd{display:block}._sage var,._sage var a{color:#268bd2;font-style:normal}._sage dt:hover var,._sage dt:hover var a{color:#2aa198}._sage dfn{font-style:normal;font-weight:normal;color:#586e75}._sage pre{color:#657b83;margin:0 0 0 12px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block;word-break:normal}._sage ._sage-popup-trigger{float:right !important;cursor:pointer;color:#268bd2}._sage ._sage-popup-trigger:hover{color:#93a1a1}._sage dt._sage-parent>._sage-popup-trigger{font-size:13px}._sage footer{padding:0 3px 3px;font-size:9px}._sage footer>._sage-popup-trigger{font-size:12px}._sage footer nav{background-size:10px;height:10px;width:10px}._sage footer nav:hover{background-position:0 -10px}._sage footer>ol{display:none;margin-left:32px}._sage footer._sage-show>ol{display:block}._sage footer._sage-show nav{background-position:0 -20px}._sage footer._sage-show nav:hover{background-position:0 -30px}._sage a{color:#657b83;text-shadow:none}._sage a:hover{color:#586e75;border-bottom:1px dotted #586e75}._sage ul{list-style:none;padding-left:12px}._sage ul:not(._sage-tabs) li{border-left:1px dashed #93a1a1}._sage ul:not(._sage-tabs) li>dl{border-left:none}._sage ul._sage-tabs{margin:0 0 0 12px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}._sage ul._sage-tabs li{background:#eee8d5;border:1px solid #93a1a1;cursor:pointer;display:inline-block;height:24px;margin:2px;padding:0 12px;vertical-align:top}._sage ul._sage-tabs li:hover,._sage ul._sage-tabs li._sage-active-tab:hover{border-color:#268bd2;color:#2aa198}._sage ul._sage-tabs li._sage-active-tab{background:#fdf6e3;border-top:0;margin-top:-1px;height:27px;line-height:24px}._sage ul._sage-tabs li:not(._sage-active-tab){line-height:20px}._sage ul._sage-tabs li+li{margin-left:0}._sage ul:not(._sage-tabs)>li:not(:first-child){display:none}._sage dt:hover+dd>ul>li._sage-active-tab{border-color:#268bd2;color:#2aa198}._sage-report{border-collapse:collapse;empty-cells:show;border-spacing:0}._sage-report *{font-size:12px}._sage-report dt{background:none;padding:2px}._sage-report dt ._sage-parent{min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._sage-report td,._sage-report th{border:1px solid #93a1a1;padding:2px;vertical-align:center}._sage-report th{cursor:alias}._sage-report td:first-child,._sage-report th{font-weight:bold;background:#eee8d5;color:#586e75}._sage-report td{background:#fdf6e3;white-space:pre}._sage-report td>dl{padding:0}._sage-report pre{border-top:0;border-right:0}._sage-report th:first-child{background:none;border:0}._sage-report td._sage-empty{background:#d33682 !important}._sage-report tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}._sage-report tr:hover var{color:#2aa198}._sage-report ul._sage-tabs li._sage-active-tab{height:20px;line-height:17px}._sage-trace ._sage-source{line-height:14px}._sage-trace ._sage-source span{padding-right:1px;border-right:3px inset #268bd2}._sage-trace ._sage-source ._sage-highlight{background:#eee8d5}._sage-trace ._sage-parent>b{min-width:18px;display:inline-block;text-align:right;color:#586e75}._sage-trace ._sage-parent>var>a{color:#268bd2}._sage-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}._sage-microtime,._sage-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}._sage footer li{color:#ddd}._sage>dl>dt,._sage ul._sage-tabs{box-shadow:4px 0 2px -3px #268bd2 inset}._sage ul._sage-tabs li._sage-active-tab{padding-top:7px;height:34px}
diff --git a/resources/css/base.scss b/resources/css/base.scss
index d2c22d8..5e3a074 100644
--- a/resources/css/base.scss
+++ b/resources/css/base.scss
@@ -67,7 +67,6 @@ $border: 1px solid $border-color;
}
-
}
> dl dl {
@@ -88,6 +87,10 @@ $border: 1px solid $border-color;
vertical-align: middle;
}
+ dt._sage-parent {
+ cursor: pointer;
+ }
+
dt._sage-parent:hover nav {
background-position: 0 -15px;
}
diff --git a/resources/js/base.js b/resources/js/base.js
index 5d1ce16..97ec7a9 100644
--- a/resources/js/base.js
+++ b/resources/js/base.js
@@ -100,26 +100,15 @@ if (typeof _sageInitialized === 'undefined') {
switchTab: function (target) {
let lis, el = target, index = 0;
- target.parentNode.getElementsByClassName('_sage-active-tab')[0].className = '';
+ _sage.removeClass(target.parentNode.getElementsByClassName('_sage-active-tab')[0], '_sage-active-tab');
target.className = '_sage-active-tab';
// take the index of clicked title tab and make the same n-th content tab visible
while (el = el.previousSibling) el.nodeType === 1 && index++;
+
lis = target.parentNode.nextSibling.childNodes;
for (let i = 0; i < lis.length; i++) {
- if (i === index) {
- lis[i].style.display = 'block';
-
- if (lis[i].childNodes.length === 1) {
- el = lis[i].childNodes[0].childNodes[0];
-
- if (_sage.hasClass(el, '_sage-parent')) {
- _sage.toggle(el, false)
- }
- }
- } else {
- lis[i].style.display = 'none';
- }
+ lis[i].style.display = i === index ? 'block' : 'none';
}
},
@@ -289,9 +278,8 @@ if (typeof _sageInitialized === 'undefined') {
} else if (_sage.hasClass(target, '_sage-ide-link')) {
e.preventDefault();
const ajax = new XMLHttpRequest(); // add ajax call to contact editor but prevent link default action
- ajax.open('GET', target.href);
- ajax.send(null);
- return false;
+ ajax.open('get', target.href);
+ ajax.send();
} else if (_sage.hasClass(target, '_sage-popup-trigger')) {
let _sageContainer = target.parentNode;
if (_sageContainer.nodeName.toLowerCase() === 'footer') {
@@ -326,6 +314,7 @@ if (typeof _sageInitialized === 'undefined') {
// do nothing if alt/ctrl key is pressed or if we're actually typing somewhere
if (e.target !== document.body || e.altKey || e.ctrlKey) return;
+ // todo use e.key https://www.toptal.com/developers/keycode
const keyCode = e.keyCode
, shiftKey = e.shiftKey
let i = _sage.currentPlus;
diff --git a/sage.phar b/sage.phar
index b4238cb..fa19061 100644
Binary files a/sage.phar and b/sage.phar differ