From 9461cefc35588a84031c3076ebc671882c665d11 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 11 Oct 2019 12:00:48 -0400 Subject: [PATCH 01/20] Upgrade Daux to 0.11 --- RoboFile.php | 72 +------ .../030_Keeping_Newsfeeds_Up_to_Date.md | 2 +- docs/theme/arsse/arsse.css | 2 +- docs/theme/arsse/config.json | 3 +- docs/theme/arsse/daux.js | 182 ------------------ docs/theme/arsse/daux.min.js | 2 + docs/theme/arsse/highlight.pack.js | 2 - docs/theme/src/arsse.scss | 16 +- vendor-bin/daux/composer.json | 2 +- vendor-bin/daux/composer.lock | 150 +++++++++++---- 10 files changed, 129 insertions(+), 304 deletions(-) delete mode 100644 docs/theme/arsse/daux.js create mode 100644 docs/theme/arsse/daux.min.js delete mode 100644 docs/theme/arsse/highlight.pack.js diff --git a/RoboFile.php b/RoboFile.php index e47c8fc..0bb505a 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -213,80 +213,20 @@ class RoboFile extends \Robo\Tasks { * Daux's theme changes */ public function manualTheme(array $args): Result { - $languages = ["php", "bash", "shell", "xml", "nginx", "apache"]; + $postcss = escapeshellarg(norm(BASE."node_modules/.bin/postcss")); + $themesrc = norm(BASE."docs/theme/src/").\DIRECTORY_SEPARATOR; $themeout = norm(BASE."docs/theme/arsse/").\DIRECTORY_SEPARATOR; $dauxjs = norm(BASE."vendor-bin/daux/vendor/daux/daux.io/themes/daux/js/").\DIRECTORY_SEPARATOR; // start a collection; this stops after the first failure $t = $this->collectionBuilder(); - $tmp = $t->tmpDir().\DIRECTORY_SEPARATOR; - // rebuild the stylesheet - $t->addCode([$this, "manualCss"]); - // copy JavaScript files from the Daux theme - foreach (glob($dauxjs."daux*") as $file) { - $t->taskFilesystemStack()->copy($file, $themeout.basename($file), true); - } - // download highlight.js - $t->addCode(function() use ($languages, $tmp, $themeout) { - // compile the list of desired language (enumerated above) into an application/x-www-form-urlencoded body - $post = http_build_query((function($langs) { - $out = []; - foreach ($langs as $l) { - $out[$l.".js"] = "on"; - } - return $out; - })($languages)); - // get the two cross-site request forgery tokens the Highlight.js Web site requires - $conn = @fopen("https://highlightjs.org/download/", "r"); - if ($conn === false) { - throw new Exception("Unable to download Highlight.js"); - } - foreach (stream_get_meta_data($conn)['wrapper_data'] as $field) { - if (preg_match("/^Set-Cookie: csrftoken=([^;]+)/i", $field, $cookie)) { - break; - } - } - $token = stream_get_contents($conn); - preg_match("/ [ - 'method' => "POST", - 'content' => $post, - 'header' => [ - "Referer: https://highlightjs.org/download/", - "Cookie: csrftoken={$cookie[1]}", - "Content-Type: application/x-www-form-urlencoded", - ], - ]])); - if ($hljs === false) { - throw new Exception("Unable to download Highlight.js"); - } else { - file_put_contents($tmp."highlightjs.zip", $hljs); - } - // extract the downloaded zip file and keep only the JS file - $this->taskExtract($tmp."highlightjs.zip")->to($tmp."hljs")->run(); - $this->taskFilesystemStack()->copy($tmp."hljs".\DIRECTORY_SEPARATOR."highlight.pack.js", $themeout."highlight.pack.js")->run(); - }, "downloadHighlightjs"); - // execute the collection - return $t->run(); - } - - /** Rebuilds the manual theme's stylesheet only - * - * This requires Node and Yarn to be installed. - */ - public function manualCss(): Result { - // start a collection; this stops after the first failure - $t = $this->collectionBuilder(); - $tmp = $t->tmpDir().\DIRECTORY_SEPARATOR; // install dependencies via Yarn $t->taskExec("yarn install"); // compile the stylesheet - $postcss = escapeshellarg(norm(BASE."node_modules/.bin/postcss")); - $themesrc = norm(BASE."docs/theme/src/").\DIRECTORY_SEPARATOR; - $themeout = norm(BASE."docs/theme/arsse/").\DIRECTORY_SEPARATOR; $t->taskExec($postcss)->arg($themesrc."arsse.scss")->option("-o", $themeout."arsse.css"); + // copy JavaScript files from the Daux theme + foreach (glob($dauxjs."daux*.js") as $file) { + $t->taskFilesystemStack()->copy($file, $themeout.basename($file), true); + } // execute the collection return $t->run(); } diff --git a/docs/en/025_Using_The_Arsse/030_Keeping_Newsfeeds_Up_to_Date.md b/docs/en/025_Using_The_Arsse/030_Keeping_Newsfeeds_Up_to_Date.md index 4d293e2..837de68 100644 --- a/docs/en/025_Using_The_Arsse/030_Keeping_Newsfeeds_Up_to_Date.md +++ b/docs/en/025_Using_The_Arsse/030_Keeping_Newsfeeds_Up_to_Date.md @@ -32,7 +32,7 @@ sudo crontab -u www-data -e And add a line such as this one: -```cron +``` */2 * * * * /usr/bin/env php /usr/share/arsse/arsse.php refresh-all ``` diff --git a/docs/theme/arsse/arsse.css b/docs/theme/arsse/arsse.css index 925ac3e..bc6a19c 100644 --- a/docs/theme/arsse/arsse.css +++ b/docs/theme/arsse/arsse.css @@ -1,2 +1,2 @@ /*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size:14px}body{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress,sub,sup{vertical-align:baseline}.s-content pre code:after,.s-content pre code:before,[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects;text-decoration:none;color:#e63c2f}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}.s-content blockquote cite,dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;clear:both;margin:1em 0;border:0;border-top:1px solid #ddd}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,hr,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{color:inherit;display:table;max-width:100%;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}*,:after,:before{box-sizing:border-box}@media (min-width:850px){html{font-size:16px}}body,html{height:100%;background-color:#fff;color:#15284b}.Columns__left{background-color:#e8d5d3}.Columns__right__content{padding:10px;background-color:#fff}@media (max-width:768px){html:not(.no-js) .Collapsible__content{height:0;overflow:hidden;transition:height 400ms ease-in-out}}.Collapsible__trigger{margin:12px;padding:7px 10px;background-color:transparent;border:0;float:right;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}.Collapsible__trigger__bar{display:block;width:18px;height:2px;margin-top:2px;margin-bottom:3px;background-color:#e8d5d3}.Collapsible__trigger:hover{background-color:#93b7bb;box-shadow:none}.Collapsible__trigger:hover .Collapsible__trigger__bar{background-color:#15284b}@media screen and (min-width:769px){body{background-color:#15284b}.Navbar{position:fixed;z-index:1030;width:100%}.Collapsible__trigger{display:none!important}.Collapsible__content{display:block!important}.Columns{height:100%}.Columns:after,.Columns:before{content:" ";display:table}.Columns:after{clear:both}.Columns__left,.Columns__right{position:relative;min-height:1px;float:left;overflow:auto;height:100%}.Columns__left{width:25%;border-right:1px solid #e7e7e9;overflow-x:hidden}.Columns__right{width:75%}.Columns__right__content{padding:0 20px 20px;min-height:100%}}body{font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-feature-settings:"kern" 1;-webkit-font-kerning:normal;font-kerning:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;line-height:1.618}h1,h2,h3,h4,h5,h6{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.s-content h1,.s-content h2,.s-content h3,.s-content h4,.s-content h5,.s-content h6{cursor:text;line-height:1.4em;margin:2em 0 .5em}.s-content h1 code,.s-content h1 tt,.s-content h2 code,.s-content h2 tt,.s-content h3 code,.s-content h3 tt,.s-content h4 code,.s-content h4 tt,.s-content h5 code,.s-content h5 tt,.s-content h6 code,.s-content h6 tt{font-size:inherit}.s-content h1 i,.s-content h2 i,.s-content h3 i,.s-content h4 i,.s-content h5 i,.s-content h6 i{font-size:.7em}.s-content h1 p,.s-content h2 p,.s-content h3 p,.s-content h4 p,.s-content h5 p,.s-content h6 p{margin-top:0}.s-content h1{margin-top:0;font-size:2.618rem}.s-content h2{font-size:2rem}.s-content h3{font-size:1.618rem}.s-content h4,.s-content h5,.s-content h6,.s-content small{font-size:1.309rem}.s-content a{text-decoration:underline}.s-content p{margin-bottom:1.3em}.s-content ol,.s-content ul{padding-left:2em}.s-content ul p,.s-content ul ul{margin:0}.s-content dl{padding:0}.s-content dl dt{font-weight:700;font-style:italic;padding:0;margin:15px 0 5px}.s-content dl dt:first-child{padding:0}.s-content dl dd{margin:0 0 15px;padding:0 15px}.s-content blockquote{margin:.75em 2em;padding:.5em 1em;font-style:italic;border-left:.25em solid #15284b}.s-content blockquote cite:before{content:"\2014";padding-right:.5em}.s-content table{width:100%;padding:0;margin-bottom:1em;border-collapse:separate;border-spacing:2px;border:2px solid #b3aab1}.s-content table+table{margin-top:1em}.s-content table tr{background-color:#fff;margin:0;padding:0;border-top:0}.s-content table tr:nth-child(2n){background-color:transparent}.s-content table th{font-weight:700;background:#e8d5d3}.s-content table td,.s-content table th{margin:0;padding:.5em}.s-content blockquote>:first-child,.s-content dl dd>:first-child,.s-content dl dt>:first-child,.s-content ol>:first-child,.s-content table td>:first-child,.s-content table th>:first-child,.s-content ul>:first-child{margin-top:0}.s-content blockquote>:last-child,.s-content dl dd>:last-child,.s-content dl dt>:last-child,.s-content ol>:last-child,.s-content table td>:last-child,.s-content table th>:last-child,.s-content ul>:last-child{margin-bottom:0}.s-content img{max-width:100%;display:block;margin:0 auto}.s-content code{font-family:Monaco,Menlo,Consolas,"Lucida Console","Courier New",monospace;padding-top:.1rem;padding-bottom:.1rem;background:#f9f5f4;border-radius:0;box-shadow:none;display:inline-block;padding:.5ch;border:0}.s-content code:after,.s-content code:before{letter-spacing:-.2em;content:"\00a0"}.s-content pre{background:#fdf6e3;line-height:1.5em;overflow:auto;border:0;border-radius:0;padding:.75em 2em;margin:0 -20px 20px}.s-content pre code{margin:0;padding:0;white-space:pre;box-shadow:none}.s-content pre code,.s-content pre tt{background-color:transparent;border:0}.s-content ins,.s-content u{text-decoration:none;border-bottom:1px solid #15284b}.s-content del a,.s-content ins a,.s-content u a{color:inherit}@media (min-width:1150px){.Columns__right--float .Columns__right__content{height:100%;overflow:auto;padding:0!important;background-color:transparent!important;position:relative}.Columns__right--float .Columns__right__content article{width:100%;min-height:100%;overflow:auto;position:relative;z-index:1}.Columns__right--float .Columns__right__content article:before{content:"";width:50%;min-height:100%;overflow:auto;background-color:#fff;display:block;margin:0;position:absolute;z-index:-1}.Columns__right--float .Page__header,.Columns__right--float .Pager,.Columns__right--float .s-content blockquote,.Columns__right--float .s-content dl,.Columns__right--float .s-content h2,.Columns__right--float .s-content h3,.Columns__right--float .s-content h4,.Columns__right--float .s-content h5,.Columns__right--float .s-content h6,.Columns__right--float .s-content hr,.Columns__right--float .s-content ol,.Columns__right--float .s-content p,.Columns__right--float .s-content table,.Columns__right--float .s-content ul{float:left;clear:left;width:47%;margin-left:1.5%;margin-right:1.5%}.Columns__right--float .s-content table{background-color:#fff;white-space:normal}.Columns__right--float .s-content table code,.Columns__right--float .s-content table pre{white-space:normal}.Columns__right--float .s-content blockquote:before,.Columns__right--float .s-content dl:before,.Columns__right--float .s-content h2:before,.Columns__right--float .s-content h3:before,.Columns__right--float .s-content h4:before,.Columns__right--float .s-content h5:before,.Columns__right--float .s-content h6:before,.Columns__right--float .s-content hr:before,.Columns__right--float .s-content ol:before,.Columns__right--float .s-content p:before,.Columns__right--float .s-content ul:before{width:100%;height:10px;display:block;clear:both}.Columns__right--float .s-content blockquote p,.Columns__right--float .s-content blockquote pre{float:none;display:block}.Columns__right--float .s-content blockquote dl,.Columns__right--float .s-content blockquote h2,.Columns__right--float .s-content blockquote h3,.Columns__right--float .s-content blockquote h4,.Columns__right--float .s-content blockquote h5,.Columns__right--float .s-content blockquote h6,.Columns__right--float .s-content blockquote hr,.Columns__right--float .s-content blockquote ol,.Columns__right--float .s-content blockquote ul,.Columns__right--float .s-content dl dl,.Columns__right--float .s-content dl h2,.Columns__right--float .s-content dl h3,.Columns__right--float .s-content dl h4,.Columns__right--float .s-content dl h5,.Columns__right--float .s-content dl h6,.Columns__right--float .s-content dl hr,.Columns__right--float .s-content dl ol,.Columns__right--float .s-content dl p,.Columns__right--float .s-content dl pre,.Columns__right--float .s-content dl ul,.Columns__right--float .s-content h2 dl,.Columns__right--float .s-content h2 h2,.Columns__right--float .s-content h2 h3,.Columns__right--float .s-content h2 h4,.Columns__right--float .s-content h2 h5,.Columns__right--float .s-content h2 h6,.Columns__right--float .s-content h2 hr,.Columns__right--float .s-content h2 ol,.Columns__right--float .s-content h2 p,.Columns__right--float .s-content h2 pre,.Columns__right--float .s-content h2 ul,.Columns__right--float .s-content h3 dl,.Columns__right--float .s-content h3 h2,.Columns__right--float .s-content h3 h3,.Columns__right--float .s-content h3 h4,.Columns__right--float .s-content h3 h5,.Columns__right--float .s-content h3 h6,.Columns__right--float .s-content h3 hr,.Columns__right--float .s-content h3 ol,.Columns__right--float .s-content h3 p,.Columns__right--float .s-content h3 pre,.Columns__right--float .s-content h3 ul,.Columns__right--float .s-content h4 dl,.Columns__right--float .s-content h4 h2,.Columns__right--float .s-content h4 h3,.Columns__right--float .s-content h4 h4,.Columns__right--float .s-content h4 h5,.Columns__right--float .s-content h4 h6,.Columns__right--float .s-content h4 hr,.Columns__right--float .s-content h4 ol,.Columns__right--float .s-content h4 p,.Columns__right--float .s-content h4 pre,.Columns__right--float .s-content h4 ul,.Columns__right--float .s-content h5 dl,.Columns__right--float .s-content h5 h2,.Columns__right--float .s-content h5 h3,.Columns__right--float .s-content h5 h4,.Columns__right--float .s-content h5 h5,.Columns__right--float .s-content h5 h6,.Columns__right--float .s-content h5 hr,.Columns__right--float .s-content h5 ol,.Columns__right--float .s-content h5 p,.Columns__right--float .s-content h5 pre,.Columns__right--float .s-content h5 ul,.Columns__right--float .s-content h6 dl,.Columns__right--float .s-content h6 h2,.Columns__right--float .s-content h6 h3,.Columns__right--float .s-content h6 h4,.Columns__right--float .s-content h6 h5,.Columns__right--float .s-content h6 h6,.Columns__right--float .s-content h6 hr,.Columns__right--float .s-content h6 ol,.Columns__right--float .s-content h6 p,.Columns__right--float .s-content h6 pre,.Columns__right--float .s-content h6 ul,.Columns__right--float .s-content hr dl,.Columns__right--float .s-content hr h2,.Columns__right--float .s-content hr h3,.Columns__right--float .s-content hr h4,.Columns__right--float .s-content hr h5,.Columns__right--float .s-content hr h6,.Columns__right--float .s-content hr hr,.Columns__right--float .s-content hr ol,.Columns__right--float .s-content hr p,.Columns__right--float .s-content hr pre,.Columns__right--float .s-content hr ul,.Columns__right--float .s-content ol dl,.Columns__right--float .s-content ol h2,.Columns__right--float .s-content ol h3,.Columns__right--float .s-content ol h4,.Columns__right--float .s-content ol h5,.Columns__right--float .s-content ol h6,.Columns__right--float .s-content ol hr,.Columns__right--float .s-content ol ol,.Columns__right--float .s-content ol p,.Columns__right--float .s-content ol pre,.Columns__right--float .s-content ol ul,.Columns__right--float .s-content p dl,.Columns__right--float .s-content p h2,.Columns__right--float .s-content p h3,.Columns__right--float .s-content p h4,.Columns__right--float .s-content p h5,.Columns__right--float .s-content p h6,.Columns__right--float .s-content p hr,.Columns__right--float .s-content p ol,.Columns__right--float .s-content p p,.Columns__right--float .s-content p pre,.Columns__right--float .s-content p ul,.Columns__right--float .s-content ul dl,.Columns__right--float .s-content ul h2,.Columns__right--float .s-content ul h3,.Columns__right--float .s-content ul h4,.Columns__right--float .s-content ul h5,.Columns__right--float .s-content ul h6,.Columns__right--float .s-content ul hr,.Columns__right--float .s-content ul ol,.Columns__right--float .s-content ul p,.Columns__right--float .s-content ul pre,.Columns__right--float .s-content ul ul{width:auto;float:none;display:block}.Columns__right--float .s-content hr{border-color:#ddd}.Columns__right--float .s-content blockquote p,.Columns__right--float .s-content blockquote pre,.Columns__right--float .s-content li p,.Columns__right--float .s-content li pre{width:100%}.Columns__right--float .s-content pre{float:left;clear:right;width:50%;border:0;border-left:10px solid #fff;margin:0 0 10px;padding:0}.Columns__right--float .s-content pre code{padding:0 .5em}}a.Link--external:after{content:" " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=)}a.Link--broken{color:red}p{margin:0 0 1em}.Button{display:inline-block;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;margin-bottom:0}.Button--small{font-size:12px;line-height:1.5;border-radius:3px}.Button--default{color:#333;background-color:#fff;border-color:#ccc}.Button--default.Button--active{color:#333;background-color:#e6e6e6;border-color:#adadad}.ButtonGroup{position:relative;display:inline-block;vertical-align:middle}.ButtonGroup .Button+.Button{margin-left:-1px}.ButtonGroup>.Button{position:relative;float:left}.ButtonGroup>.Button:focus,.ButtonGroup>.Button:hover{z-index:2}.ButtonGroup>.Button.Button--active,.ButtonGroup>.Button:active{z-index:3}.ButtonGroup>.Button:not(:first-child):not(:last-child){border-radius:0}.ButtonGroup>.Button:first-child{margin-left:0}.ButtonGroup>.Button:first-child:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.ButtonGroup>.Button:last-child:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.Brand,.Navbar{background-color:#e63c2f}.Brand{display:block;padding:.75em .6em;font-size:2rem;text-shadow:none;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b}.Navbar{box-shadow:0 1px 5px rgba(0,0,0,.25);margin-bottom:0}.CodeToggler{padding:0 20px}.CodeToggler__text{font-size:12px;line-height:1.5;padding:6px 10px 6px 0;display:inline-block;vertical-align:middle}.no-js .CodeToggler{display:none}.Nav{margin:0;padding:0}.Nav__arrow{display:inline-block;position:relative;width:16px;margin-left:-16px}.Nav__arrow:before{position:absolute;display:block;content:"";margin:-.25em 0 0 -.4em;left:50%;top:50%;border-right:.15em solid #15284b;border-top:.15em solid #15284b;transform:rotate(45deg);transition-duration:.3s}.Nav__item,.Nav__item a{display:block}.Nav__item a{margin:0;padding:6px 15px 6px 20px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;text-shadow:none}.Nav__item a:hover{color:#15284b;text-shadow:none;background-color:#93b7bb}.Nav .Nav{margin-left:15px}html:not(.no-js) .Nav .Nav{height:0;transition:height 400ms ease-in-out;overflow:hidden}.Nav .Nav .Nav__item a{margin:0 0 0 -15px;padding:3px 30px;font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b;opacity:.7}.Nav .Nav .Nav__item a:hover{opacity:1}.Nav .Nav .Nav__item--active a{color:#15284b}.Nav__item--active>a,.Nav__item--open>a{background-color:#93b7bb}.Nav__item--open>a>.Nav__arrow:before{margin-left:-.25em;transform:rotate(135deg)}.Page__header{margin:0 0 10px;padding:0}.Page__header:after,.Page__header:before{content:" ";display:table}.Page__header:after{clear:both}.Page__header h1{margin:0;padding:0;line-height:57px}.Page__header--separator{height:.6em}.Page__header a,ul.TableOfContents a{text-decoration:none}.Page__header .EditOn,.Page__header .ModifiedDate{float:left;font-size:10px;color:gray}.Page__header .EditOn{float:right}.Links,.Twitter{padding:0 20px}.Links a{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;line-height:2em}.PoweredBy{padding:0 20px 1rem;font-size:1.309rem}.Search{position:relative}.Search__field{display:block;width:100%;height:34px;padding:6px 30px 6px 20px;color:#555;border-width:0 0 1px;border-bottom:1px solid #ccc;background:#fff;transition:border-color ease-in-out .15s}.Search__field:focus{border-color:#93b7bb;outline:0}.Search__icon{position:absolute;right:9px;top:9px;width:16px;height:16px}.Navbar .Search{float:right;margin:8px 20px}.Navbar .Search__field{box-shadow:inset 0 1px 1px rgba(0,0,0,.075);border-width:0;border-radius:4px;padding-left:10px}.TableOfContentsContainer__title{margin-bottom:0!important}.TableOfContentsContainer__content>.TableOfContents{margin-top:0}ul.TableOfContents{float:none;font-size:16px;padding-left:1.5em;border-left:6px solid #e8d5d3}ul.TableOfContents p{margin-bottom:0}ul.TableOfContents .TableOfContents{border-left-width:0}.Columns__right--full .TableOfContentsContainer{float:right;min-width:300px;max-width:25%;padding-left:1em}.Columns__right--full .TableOfContentsContainer .TableOfContentsContainer__content>.TableOfContents{border-right:2px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer .TableOfContents{list-style-type:none;padding-left:0}.Columns__right--full .TableOfContentsContainer a{display:block;padding:.2em 0;border-bottom:1px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer li a{padding-left:.75em}.Columns__right--full .TableOfContentsContainer li li a{padding-left:1.5em}.Columns__right--full .TableOfContentsContainer li li li a{padding-left:2.25em}.Columns__right--full .TableOfContentsContainer li li li li a{padding-left:3em}.Pager{padding-left:0;margin:1em 0;list-style:none;text-align:center}.Pager:after,.Pager:before{content:" ";display:table}.Pager,.Pager:after{clear:both}.Pager li{display:inline}.Pager li>a{display:inline-block;padding:5px 14px;background-color:#fff}.Pager li>a:focus,.Pager li>a:hover{text-decoration:none}.Pager--next>a{float:right}.Pager--prev>a{float:left}.Checkbox{position:relative;display:block;padding-left:30px;cursor:pointer}.Checkbox input{position:absolute;z-index:-1;opacity:0}.Checkbox__indicator{position:absolute;top:50%;left:0;width:20px;height:20px;margin-top:-10px;background:#e6e6e6}.Checkbox__indicator:after{position:absolute;display:none;content:""}.Checkbox input:focus~.Checkbox__indicator,.Checkbox:hover input~.Checkbox__indicator{background:#ccc}.Checkbox input:checked~.Checkbox__indicator{background:#15284b}.Checkbox input:checked~.Checkbox__indicator:after{display:block}.Checkbox input:checked:focus~.Checkbox__indicator,.Checkbox:hover input:not([disabled]):checked~.Checkbox__indicator{background:#93b7bb}.Checkbox input:disabled~.Checkbox__indicator{pointer-events:none;opacity:.6;background:#e6e6e6}.Checkbox .Checkbox__indicator:after{top:4px;left:8px;width:5px;height:10px;transform:rotate(45deg);border:solid #fff;border-width:0 2px 2px 0}.Checkbox input:disabled~.Checkbox__indicator:after{border-color:#7b7b7b}.Hidden{display:none}.Container{margin-right:auto;margin-left:auto}.Container--inner{width:80%;margin:0 auto}@media (min-width:1200px){.Container{width:1170px}}@media (min-width:992px){.Container{width:970px}}@media (min-width:769px){.Container{width:750px}}@media (min-width:1200px){.Container{width:1170px}}.Homepage{background-color:#fff;border-radius:0;border:0;color:#15284b;overflow:hidden;padding-bottom:0;margin-bottom:0;box-shadow:none}.HomepageTitle h2{width:80%;font-size:30px;margin:20px auto;text-align:center}.HomepageImage img{display:block;max-width:80%;margin:0 auto;height:auto}.HomepageButtons{padding:20px 0;background-color:#e8d5d3;text-align:center}.HomepageButtons:after,.HomepageButtons:before{content:" ";display:table}.HomepageButtons:after{clear:both}.HomepageButtons .Button--hero{padding:20px 30px;border-radius:0;text-shadow:none;opacity:.8;margin:0 10px;text-transform:uppercase;border:5px solid #15284b;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}@media (max-width:768px){.HomepageButtons .Button--hero{display:block;margin-bottom:10px}}.HomepageButtons .Button--hero:hover{opacity:1}.HomepageButtons .Button--hero.Button--secondary{background-color:#93b7bb;color:#15284b}.HomepageButtons .Button--hero.Button--primary{background-color:#15284b;color:#e8d5d3}.HomepageContent{background-color:#fff;padding:40px 0}.HomepageContent ol li,.HomepageContent ul li{list-style:none;margin-bottom:.5em;position:relative}.HomepageContent ol li:before,.HomepageContent ul li:before{position:absolute;top:50%;left:-1.5em;content:"";width:0;height:0;border:.5em solid transparent;border-left:.5em solid #93b7bb;float:left;display:block;margin-top:-.5em}.HomepageContent .HeroText,.HomepageFooter__links li a{font-size:16px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.HomepageContent .HeroText{margin-bottom:20px;font-weight:300;line-height:1.4}@media (min-width:769px){.HomepageContent{padding:40px 20px}.HomepageContent .HeroText{font-size:21px}.HomepageContent .Row{margin:0 -15px}.HomepageContent .Row__half,.HomepageContent .Row__quarter,.HomepageContent .Row__third{float:left;position:relative;min-height:1px;padding-left:15px;padding-right:15px}.HomepageContent .Row__third{width:33.333333%}.HomepageContent .Row__half{width:50%}.HomepageContent .Row__quarter{width:25%}}.HomepageFooter{background-color:#15284b;color:#93b7bb;border:0;box-shadow:none}.HomepageFooter:after,.HomepageFooter:before{content:" ";display:table}.HomepageFooter:after{clear:both}@media (max-width:768px){.HomepageFooter{padding:0 20px;text-align:center}.HomepageFooter .HomepageFooter__links{padding-left:0;list-style-type:none}}@media (min-width:769px){.HomepageFooter .HomepageFooter__links{float:left}.HomepageFooter .HomepageFooter__twitter{float:right}}.HomepageFooter__links,.HomepageFooter__twitter{margin:40px 0}.HomepageFooter__links li a{line-height:32px;font-weight:700}.HomepageFooter__links li a:hover{text-decoration:underline}.HomepageFooter .Twitter{margin-bottom:20px}@media print{*{text-shadow:none!important;color:#000!important;background:0 0!important;box-shadow:none!important}h1,h2,h3,h4,h5,h6{page-break-after:avoid;page-break-before:auto}blockquote,img,pre{page-break-inside:avoid}blockquote,pre{font-style:italic;border:1px solid #999}img{border:0}a,a:visited{text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}q{quotes:none}.s-content a[href^="#"]:after,q:before{content:""}q:after{content:" (" attr(cite) ")"}.PageBreak{display:block;page-break-before:always}.NoPrint,.Pager,aside{display:none}.Columns__right{width:100%!important}.s-content a:after{content:" (" attr(href) ")";font-size:80%;word-wrap:break-word}h1 a[href]:after{font-size:50%}}@font-face{font-family:'League Gothic';src:url(fonts/leaguegothic.woff2) format('woff2'),url(fonts/leaguegothic.woff) format('woff');font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-regular.woff2) format('woff2'),url(fonts/cabin-regular.woff) format('woff');font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-italic.woff2) format('woff2'),url(fonts/cabin-italic.woff) format('woff');font-style:italic;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-bold.woff2) format('woff2'),url(fonts/cabin-bold.woff) format('woff');font-weight:700;font-style:normal;font-display:swap}.s-content code::after,.s-content code::before,a.Link--external::after{content:''}pre .s-content code{display:inline}.s-content table tbody,.s-content table thead{background-color:#fff}.s-content table tr:nth-child(2n) td{background-color:#f9f5f4}.s-content table td,.s-content table th{border:0}.Nav__item .Nav__item,.s-content table{font-size:1rem}.Brand,h1,h2,h3,h4,h5,h6{font-weight:400}.Button,.Pager li>a{border-radius:0}.HomepageButtons .Button--hero{font-weight:400;font-size:1.309rem}.Page__header{border-bottom:2px solid #e8d5d3}.Pager li>a{border:2px solid #e8d5d3}.Pager li>a:focus,.Pager li>a:hover{background-color:#e8d5d3}.Pager--prev a::before{content:"\2190\00a0"}.Pager--next a::after{content:"\00a0\2192"}.Navbar{height:auto;box-shadow:none}.Navbar .Brand{float:none;line-height:inherit;height:auto}.Homepage{padding-top:10px!important}.Nav__item{font-size:1.309rem}.Nav .Nav .Nav__item a .Nav__arrow:before,.Nav__arrow:before{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;width:1ch;height:1ch}.TableOfContentsContainer__title{border-bottom:4px solid #e8d5d3}.clients thead tr:first-child th{text-align:left}.clients thead tr:first-child th:first-child{width:15%}.clients thead tr:first-child th:nth-child(3){width:50%;text-align:center}.clients thead tr+tr th{width:16.66%;text-align:center}.clients tbody td:nth-child(3),.clients tbody td:nth-child(4),.clients tbody td:nth-child(5){text-align:center}.clients tbody td.Y{color:#2c9a42}.clients tbody td.N{color:#e63c2f}.hljs,.s-content pre{background:#15284b;color:#e8d5d3}.hljs{display:block;overflow-x:auto;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-comment,.hljs-quote{color:#978e9c}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#acb39a}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#93b7bb}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#82b7e5}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c5b031}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#ea8031}.hljs-built_in,.hljs-deletion{color:#e63c2f}.hljs-formula{background:#686986}@media (min-width:850px){.Columns__left{border:0}} \ No newline at end of file +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size:14px}body{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress,sub,sup{vertical-align:baseline}.s-content pre code:after,.s-content pre code:before,[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects;text-decoration:none;color:#e63c2f}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}.s-content blockquote cite,dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;clear:both;margin:1em 0;border:0;border-top:1px solid #ddd}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,hr,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{color:inherit;display:table;max-width:100%;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}*,:after,:before{box-sizing:border-box}@media (min-width:850px){html{font-size:16px}}body,html{height:100%;background-color:#fff;color:#15284b}.Columns__left{background-color:#e8d5d3}.Columns__right__content{padding:10px;background-color:#fff}@media (max-width:768px){html:not(.no-js) .Collapsible__content{height:0;overflow:hidden;transition:height 400ms ease-in-out}}.Collapsible__trigger{margin:12px;padding:7px 10px;background-color:transparent;border:0;float:right;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}.Collapsible__trigger__bar{display:block;width:18px;height:2px;margin-top:2px;margin-bottom:3px;background-color:#e8d5d3}.Collapsible__trigger:hover{background-color:#93b7bb;box-shadow:none}.Collapsible__trigger:hover .Collapsible__trigger__bar{background-color:#15284b}@media screen and (min-width:769px){body{background-color:#15284b}.Navbar{position:fixed;z-index:1030;width:100%}.Collapsible__trigger{display:none!important}.Collapsible__content{display:block!important}.Columns{height:100%}.Columns:after,.Columns:before{content:" ";display:table}.Columns:after{clear:both}.Columns__left,.Columns__right{position:relative;min-height:1px;float:left;overflow:auto;height:100%}.Columns__left{width:25%;border-right:1px solid #e7e7e9;overflow-x:hidden}.Columns__right{width:75%}.Columns__right__content{padding:0 20px 20px;min-height:100%}}.Page{max-width:860px}body{font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-feature-settings:"kern" 1;-webkit-font-kerning:normal;font-kerning:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;line-height:1.618}h1,h2,h3,h4,h5,h6{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.s-content h1,.s-content h2,.s-content h3,.s-content h4,.s-content h5,.s-content h6{cursor:text;line-height:1.4em;margin:2em 0 .5em}.s-content h1 code,.s-content h1 tt,.s-content h2 code,.s-content h2 tt,.s-content h3 code,.s-content h3 tt,.s-content h4 code,.s-content h4 tt,.s-content h5 code,.s-content h5 tt,.s-content h6 code,.s-content h6 tt{font-size:inherit}.s-content h1 i,.s-content h2 i,.s-content h3 i,.s-content h4 i,.s-content h5 i,.s-content h6 i{font-size:.7em}.s-content h1 p,.s-content h2 p,.s-content h3 p,.s-content h4 p,.s-content h5 p,.s-content h6 p{margin-top:0}.s-content h1{margin-top:0;font-size:2.618rem}.s-content h2{font-size:2rem}.s-content h3{font-size:1.618rem}.s-content h4,.s-content h5,.s-content h6,.s-content small{font-size:1.309rem}.s-content a{text-decoration:underline}.s-content p{margin-bottom:1.3em}.s-content ol,.s-content ul{padding-left:2em}.s-content ul p,.s-content ul ul{margin:0}.s-content dl{padding:0}.s-content dl dt{font-weight:700;font-style:italic;padding:0;margin:15px 0 5px}.s-content dl dt:first-child{padding:0}.s-content dl dd{margin:0 0 15px;padding:0 15px}.s-content blockquote{margin:.75em 2em;padding:.5em 1em;font-style:italic;border-left:.25em solid #15284b}.s-content blockquote cite:before{content:"\2014";padding-right:.5em}.s-content table{width:100%;padding:0;margin-bottom:1em;border-collapse:separate;border-spacing:2px;border:2px solid #b3aab1}.s-content table+table{margin-top:1em}.s-content table tr{background-color:#fff;margin:0;padding:0;border-top:0}.s-content table tr:nth-child(2n){background-color:transparent}.s-content table th{font-weight:700;background:#e8d5d3}.s-content table td,.s-content table th{margin:0;padding:.5em}.s-content blockquote>:first-child,.s-content dl dd>:first-child,.s-content dl dt>:first-child,.s-content ol>:first-child,.s-content table td>:first-child,.s-content table th>:first-child,.s-content ul>:first-child{margin-top:0}.s-content blockquote>:last-child,.s-content dl dd>:last-child,.s-content dl dt>:last-child,.s-content ol>:last-child,.s-content table td>:last-child,.s-content table th>:last-child,.s-content ul>:last-child{margin-bottom:0}.s-content img{max-width:100%;display:block;margin:0 auto}.s-content code{font-family:Monaco,Menlo,Consolas,"Lucida Console","Courier New",monospace;padding-top:.1rem;padding-bottom:.1rem;background:#f9f5f4;border-radius:0;box-shadow:none;display:inline-block;padding:.5ch;border:0}.s-content code:after,.s-content code:before{letter-spacing:-.2em;content:"\00a0"}.s-content pre{background:#f5f2f0;line-height:1.5em;overflow:auto;border:0;border-radius:0;padding:.75em 20px;margin:0 -20px 20px}.s-content pre code{margin:0;padding:0;white-space:pre;box-shadow:none}.s-content pre code,.s-content pre tt{background-color:transparent;border:0}.s-content ins,.s-content u{text-decoration:none;border-bottom:1px solid #15284b}.s-content del a,.s-content ins a,.s-content u a{color:inherit}a.Link--external:after{content:" " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=)}a.Link--broken{color:red}p{margin:0 0 1em}.Button{display:inline-block;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;margin-bottom:0}.Button--small{font-size:12px;line-height:1.5;border-radius:3px}.Button--default{color:#333;background-color:#fff;border-color:#ccc}.Button--default.Button--active{color:#333;background-color:#e6e6e6;border-color:#adadad}.Brand,.Navbar{background-color:#e63c2f}.Brand{display:block;padding:.75em .6em;font-size:2rem;text-shadow:none;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b}.Navbar{box-shadow:0 1px 5px rgba(0,0,0,.25);margin-bottom:0}.CodeToggler{padding:0 20px}.CodeToggler__text{font-size:12px;line-height:1.5;padding:6px 10px 6px 0;display:inline-block;vertical-align:middle}.no-js .CodeToggler{display:none}.Nav{margin:0;padding:0}.Nav__arrow{display:inline-block;position:relative;width:16px;margin-left:-16px}.Nav__arrow:before{position:absolute;display:block;content:"";margin:-.25em 0 0 -.4em;left:50%;top:50%;border-right:.15em solid #15284b;border-top:.15em solid #15284b;transform:rotate(45deg);transition-duration:.3s}.Nav__item,.Nav__item a{display:block}.Nav__item a{margin:0;padding:6px 15px 6px 20px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;text-shadow:none}.Nav__item a:hover{color:#15284b;text-shadow:none;background-color:#93b7bb}.Nav .Nav{margin-left:15px}html:not(.no-js) .Nav .Nav{height:0;transition:height 400ms ease-in-out;overflow:hidden}.Nav .Nav .Nav__item a{margin:0 0 0 -15px;padding:3px 30px;font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b;opacity:.7}.HomepageButtons .Button--hero:hover,.Nav .Nav .Nav__item a:hover{opacity:1}.Nav .Nav .Nav__item--active a{color:#15284b}.Nav__item--active>a,.Nav__item--open>a{background-color:#93b7bb}.Nav__item--open>a>.Nav__arrow:before{margin-left:-.25em;transform:rotate(135deg)}.Page__header{margin:0 0 10px;padding:0}.Page__header:after,.Page__header:before{content:" ";display:table}.Page__header:after{clear:both}.Page__header h1{margin:0;padding:0;line-height:57px}.Page__header--separator{height:.6em}.Page__header a{text-decoration:none}.Page__header .EditOn,.Page__header .ModifiedDate{float:left;font-size:10px;color:gray}.Page__header .EditOn{float:right}.Links,.Twitter{padding:0 20px}.Links a{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;line-height:2em}.Twitter{font:11px/18px "Helvetica Neue",Arial,sans-serif}.Twitter__button{text-decoration:none;display:inline-block;vertical-align:top;zoom:1;position:relative;height:20px;box-sizing:border-box;padding:1px 8px 1px 6px;background-color:#1b95e0;color:#fff;border-radius:3px;font-weight:500;cursor:pointer}.Twitter__button .Twitter__button__label{display:inline-block;vertical-align:top;zoom:1;margin-left:3px;white-space:nowrap}.Twitter__button svg{position:relative;top:2px;display:inline-block;width:14px;height:14px}.PoweredBy{padding:0 20px 1rem;font-size:1.309rem}.Search{position:relative}.Search__field{display:block;width:100%;height:34px;padding:6px 30px 6px 20px;color:#555;border-width:0 0 1px;border-bottom:1px solid #ccc;background:#fff;transition:border-color ease-in-out .15s}.Search__field:focus{border-color:#93b7bb;outline:0}.Search__icon{position:absolute;right:9px;top:9px;width:16px;height:16px}.Navbar .Search{float:right;margin:8px 20px}.Navbar .Search__field{box-shadow:inset 0 1px 1px rgba(0,0,0,.075);border-width:0;border-radius:4px;padding-left:10px}.TableOfContentsContainer{float:right;min-width:300px;max-width:25%;padding-left:1em}.TableOfContentsContainer__title{margin-bottom:0!important}.TableOfContentsContainer__content{border:1px solid #efefef;border-width:4px 2px 2px 6px}.TableOfContentsContainer__content>.TableOfContents>li+li{border-top:1px solid #ddd}ul.TableOfContents{font-size:1rem;padding-left:0;margin:0;list-style-type:none;border-left:6px solid #e8d5d3}ul.TableOfContents p{margin-bottom:0}ul.TableOfContents a{text-decoration:none;display:block;padding:.2em 0 .2em .75em}ul.TableOfContents .TableOfContents{padding-left:.75em}.Pager{padding-left:0;margin:1em 0;list-style:none;text-align:center}.Pager:after,.Pager:before{content:" ";display:table}.Pager,.Pager:after{clear:both}.Pager li{display:inline}.Pager li>a{display:inline-block;padding:5px 14px;background-color:#fff}.Pager li>a:focus,.Pager li>a:hover{text-decoration:none}.Pager--next>a{float:right}.Pager--prev>a{float:left}.Checkbox{position:relative;display:block;padding-left:30px;cursor:pointer}.Checkbox input{position:absolute;z-index:-1;opacity:0}.Checkbox__indicator{position:absolute;top:50%;left:0;width:20px;height:20px;margin-top:-10px;background:#e6e6e6}.Checkbox__indicator:after{position:absolute;display:none;content:""}.Checkbox input:focus~.Checkbox__indicator,.Checkbox:hover input~.Checkbox__indicator{background:#ccc}.Checkbox input:checked~.Checkbox__indicator{background:#15284b}.Checkbox input:checked~.Checkbox__indicator:after{display:block}.Checkbox input:checked:focus~.Checkbox__indicator,.Checkbox:hover input:not([disabled]):checked~.Checkbox__indicator{background:#93b7bb}.Checkbox input:disabled~.Checkbox__indicator{pointer-events:none;opacity:.6;background:#e6e6e6}.Checkbox .Checkbox__indicator:after{top:4px;left:8px;width:5px;height:10px;transform:rotate(45deg);border:solid #fff;border-width:0 2px 2px 0}.Checkbox input:disabled~.Checkbox__indicator:after{border-color:#7b7b7b}.Hidden{display:none}.Container{margin-right:auto;margin-left:auto}.Container--inner{width:80%;margin:0 auto}@media (min-width:1200px){.Container{width:1170px}}@media (min-width:992px){.Container{width:970px}}@media (min-width:769px){.Container{width:750px}}.Homepage{background-color:#fff;border-radius:0;border:0;color:#15284b;overflow:hidden;padding-bottom:0;margin-bottom:0;box-shadow:none}.HomepageTitle h2{width:80%;font-size:30px;margin:20px auto;text-align:center}.HomepageImage img{display:block;max-width:80%;margin:0 auto;height:auto}.HomepageButtons{padding:20px 0;background-color:#e8d5d3;text-align:center}.HomepageButtons:after,.HomepageButtons:before{content:" ";display:table}.HomepageButtons:after{clear:both}.HomepageButtons .Button--hero{padding:20px 30px;border-radius:0;text-shadow:none;opacity:.8;margin:0 10px;text-transform:uppercase;border:5px solid #15284b;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}@media (max-width:768px){.HomepageButtons .Button--hero{display:block;margin-bottom:10px}}.HomepageButtons .Button--hero.Button--secondary{background-color:#93b7bb;color:#15284b}.HomepageButtons .Button--hero.Button--primary{background-color:#15284b;color:#e8d5d3}.HomepageContent{background-color:#fff;padding:40px 0}.HomepageContent ol li,.HomepageContent ul li{list-style:none;margin-bottom:.5em;position:relative}.HomepageContent ol li:before,.HomepageContent ul li:before{position:absolute;top:50%;left:-1.5em;content:"";width:0;height:0;border:.5em solid transparent;border-left:.5em solid #93b7bb;float:left;display:block;margin-top:-.5em}.HomepageContent .HeroText,.HomepageFooter__links li a{font-size:16px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.HomepageContent .HeroText{margin-bottom:20px;font-weight:300;line-height:1.4}@media (min-width:769px){.HomepageContent{padding:40px 20px}.HomepageContent .HeroText{font-size:21px}.HomepageContent .Row{margin:0 -15px}.HomepageContent .Row__half,.HomepageContent .Row__quarter,.HomepageContent .Row__third{float:left;position:relative;min-height:1px;padding-left:15px;padding-right:15px}.HomepageContent .Row__third{width:33.333333%}.HomepageContent .Row__half{width:50%}.HomepageContent .Row__quarter{width:25%}}.HomepageFooter{background-color:#15284b;color:#93b7bb;border:0;box-shadow:none}.HomepageFooter:after,.HomepageFooter:before{content:" ";display:table}.HomepageFooter:after{clear:both}@media (max-width:768px){.HomepageFooter{padding:0 20px;text-align:center}.HomepageFooter .HomepageFooter__links{padding-left:0;list-style-type:none}}@media (min-width:769px){.HomepageFooter .HomepageFooter__links{float:left}.HomepageFooter .HomepageFooter__twitter{float:right}}.HomepageFooter__links,.HomepageFooter__twitter{margin:40px 0}.HomepageFooter__links li a{line-height:32px;font-weight:700}.HomepageFooter__links li a:hover{text-decoration:underline}.HomepageFooter .Twitter__button{margin-bottom:20px}@media print{*{text-shadow:none!important;color:#000!important;background:0 0!important;box-shadow:none!important}h1,h2,h3,h4,h5,h6{page-break-after:avoid;page-break-before:auto}blockquote,img,pre{page-break-inside:avoid}blockquote,pre{font-style:italic;border:1px solid #999}img{border:0}a,a:visited{text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}q{quotes:none}.s-content a[href^="#"]:after,q:before{content:""}q:after{content:" (" attr(cite) ")"}.PageBreak{display:block;page-break-before:always}.NoPrint,.Pager,aside{display:none}.Columns__right{width:100%!important}.s-content a:after{content:" (" attr(href) ")";font-size:80%;word-wrap:break-word}h1 a[href]:after{font-size:50%}}@font-face{font-family:'League Gothic';src:url(fonts/leaguegothic.woff2) format('woff2'),url(fonts/leaguegothic.woff) format('woff');font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-regular.woff2) format('woff2'),url(fonts/cabin-regular.woff) format('woff');font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-italic.woff2) format('woff2'),url(fonts/cabin-italic.woff) format('woff');font-style:italic;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-bold.woff2) format('woff2'),url(fonts/cabin-bold.woff) format('woff');font-weight:700;font-style:normal;font-display:swap}.s-content code::after,.s-content code::before,a.Link--external::after{content:''}pre .s-content code{display:inline}.s-content table tbody,.s-content table thead{background-color:#fff}.s-content table tr:nth-child(2n) td{background-color:#f9f5f4}.s-content table td,.s-content table th{border:0}.Nav__item .Nav__item,.s-content table{font-size:1rem}.Brand,h1,h2,h3,h4,h5,h6{font-weight:400}.Button,.Pager li>a{border-radius:0}.HomepageButtons .Button--hero{font-weight:400;font-size:1.309rem}.Page__header{border-bottom:2px solid #e8d5d3}.Pager li>a{border:2px solid #e8d5d3}.Pager li>a:focus,.Pager li>a:hover{background-color:#e8d5d3}.Pager--prev a::before{content:"\2190\00a0"}.Pager--next a::after{content:"\00a0\2192"}.Navbar{height:auto;box-shadow:none}.Navbar .Brand{float:none;line-height:inherit;height:auto}.Homepage{padding-top:10px!important}.Nav__item{font-size:1.309rem}.Nav .Nav .Nav__item a .Nav__arrow:before,.Nav__arrow:before{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;width:1ch;height:1ch}.TableOfContentsContainer__title{border-bottom:4px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer .TableOfContentsContainer__content>.TableOfContents{border-right:2px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer a{border-bottom:1px solid #e8d5d3}.clients thead tr:first-child th{text-align:left}.clients thead tr:first-child th:first-child{width:15%}.clients thead tr:first-child th:nth-child(3){width:50%;text-align:center}.clients thead tr+tr th{width:16.66%;text-align:center}.clients tbody td:nth-child(3),.clients tbody td:nth-child(4),.clients tbody td:nth-child(5){text-align:center}.clients tbody td.Y{color:#2c9a42}.clients tbody td.N{color:#e63c2f}.hljs,.s-content pre{background:#15284b;color:#e8d5d3}.hljs{display:block;overflow-x:auto;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-comment,.hljs-quote{color:#978e9c}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#acb39a}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#93b7bb}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#82b7e5}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c5b031}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#ea8031}.hljs-built_in,.hljs-deletion{color:#e63c2f}.hljs-formula{background:#686986}@media (min-width:850px){.Columns__left{border:0}} \ No newline at end of file diff --git a/docs/theme/arsse/config.json b/docs/theme/arsse/config.json index 1528980..74f6dd2 100644 --- a/docs/theme/arsse/config.json +++ b/docs/theme/arsse/config.json @@ -1,8 +1,7 @@ { "favicon": "favicon.png", "js": [ - "highlight.pack.js", - "daux.js" + "daux.min.js" ], "css": [ "arsse.css" diff --git a/docs/theme/arsse/daux.js b/docs/theme/arsse/daux.js deleted file mode 100644 index d215f90..0000000 --- a/docs/theme/arsse/daux.js +++ /dev/null @@ -1,182 +0,0 @@ -/** global localStorage, hljs */ - -if (hljs) { - hljs.initHighlightingOnLoad(); -} - -(function() { - var codeBlocks = document.querySelectorAll(".s-content pre"); - var toggleCodeSection = document.querySelector(".CodeToggler"); - if (!toggleCodeSection) { - return; - } else if (!codeBlocks.length) { - toggleCodeSection.classList.add("Hidden"); - return; - } - - var toggleCodeBlockBtnList = toggleCodeSection.querySelectorAll(".CodeToggler__button"); - var toggleCodeBlockBtnSet = toggleCodeSection.querySelector(".CodeToggler__button--main"); // available when floating is disabled - var toggleCodeBlockBtnHide = toggleCodeSection.querySelector(".CodeToggler__button--hide"); - var toggleCodeBlockBtnBelow = toggleCodeSection.querySelector(".CodeToggler__button--below"); - var toggleCodeBlockBtnFloat = toggleCodeSection.querySelector(".CodeToggler__button--float"); - var codeBlockView = document.querySelector(".Columns__right"); - var floating = document.body.classList.contains("with-float"); - - function setCodeBlockStyle(codeBlockState) { - for (var a = 0; a < toggleCodeBlockBtnList.length; a++) { - toggleCodeBlockBtnList[a].classList.remove("Button--active"); - } - switch (codeBlockState) { - case true: // Show code blocks below (flowed); checkbox - var hidden = false; - break; - case false: // Hidden code blocks; checkbox - var hidden = true; - break; - case 2: // Show code blocks inline (floated) - toggleCodeBlockBtnFloat.classList.add("Button--active"); - codeBlockView.classList.add("Columns__right--float"); - codeBlockView.classList.remove("Columns__right--full"); - var hidden = false; - break; - case 1: // Show code blocks below (flowed) - case "checked": - toggleCodeBlockBtnBelow.classList.add("Button--active"); - codeBlockView.classList.remove("Columns__right--float"); - codeBlockView.classList.add("Columns__right--full"); - var hidden = false; - break; - case 0: // Hidden code blocks - default: - toggleCodeBlockBtnHide.classList.add("Button--active"); - codeBlockView.classList.remove("Columns__right--float"); - codeBlockView.classList.add("Columns__right--full"); - var hidden = true; - break; - } - for (var a = 0; a < codeBlocks.length; a++) { - if (hidden) { - codeBlocks[a].classList.add("Hidden"); - } else { - codeBlocks[a].classList.remove("Hidden"); - } - } - try { - localStorage.setItem("codeBlockState", +codeBlockState); - } catch (e) { - // local storage operations can fail with the file:// protocol - } - } - if (!floating) { - toggleCodeBlockBtnSet.addEventListener("change", function(ev) {setCodeBlockStyle(ev.target.checked);}, false); - } else { - toggleCodeBlockBtnHide.addEventListener("click", function() {setCodeBlockStyle(0);}, false); - toggleCodeBlockBtnBelow.addEventListener("click", function() {setCodeBlockStyle(1);}, false); - toggleCodeBlockBtnFloat.addEventListener("click", function() {setCodeBlockStyle(2);}, false); - } - - try { - var codeBlockState = localStorage.getItem("codeBlockState"); - } catch (e) { - // local storage operations can fail with the file:// protocol - var codeBlockState = null; - } - if (!codeBlockState) { - codeBlockState = floating ? 2 : 1; - } else { - codeBlockState = parseInt(codeBlockState); - } - if (!floating) { - codeBlockState = !!codeBlockState; - } - - setCodeBlockStyle(codeBlockState); -})(); - -(function() { - function debounce(func, wait) { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - }; - - clearTimeout(timeout); - timeout = setTimeout(later, wait); - }; - }; - - var navItems = document.querySelectorAll('.Nav__item.has-children i.Nav__arrow'); - - function _toggleSubMenu(ev) { - if (ev.preventDefault !== undefined) { - ev.preventDefault(); - } - - var parent = ev.target.parentNode.parentNode; - var subNav = parent.querySelector('ul.Nav'); - - if (ev.preventDefault !== undefined && parent.classList.contains('Nav__item--open')) { - // Temporarily set the height so the transition can work. - subNav.style.height = subNav.scrollHeight + 'px'; - subNav.style.transitionDuration = Math.max(subNav.scrollHeight, 150) + 'ms'; - subNav.style.height = '0px'; - parent.classList.remove('Nav__item--open'); - } else { - if (ev.preventDefault !== undefined) { - subNav.style.transitionDuration = Math.max(subNav.scrollHeight, 150) + 'ms'; - // After the transition finishes set the height to auto so child - // menus can expand properly. - subNav.addEventListener('transitionend', _setHeightToAuto); - subNav.style.height = subNav.scrollHeight + 'px'; - parent.classList.add('Nav__item--open'); - } else { - // When running at page load the transitions don't need to fire and - // the classList doesn't need to be altered. - subNav.style.height = 'auto'; - } - } - } - - function _setHeightToAuto(ev) { - if (ev.target.style.height !== '0px') { - ev.target.style.height = 'auto'; - } - - ev.target.removeEventListener('transitionend', _setHeightToAuto); - } - - // Go in reverse here because on page load the child nav items need to be - // opened first before their parents so the height on the parents can be - // calculated properly. - for (var i = navItems.length - 1, cur; i >= 0; i--) { - cur = navItems[i]; - cur.addEventListener('click', _toggleSubMenu); - - if (cur.parentNode.parentNode.classList.contains('Nav__item--open')) { - _toggleSubMenu({ target: cur }); - } - } -})(); - -(function() { - var trigger = document.querySelector('.Collapsible__trigger'); - - if (!trigger) { - return; - } - - content = document.querySelector('.Collapsible__content'); - - trigger.addEventListener('click', function(ev) { - if (content.classList.contains('Collapsible__content--open')) { - content.style.height = 0; - content.classList.remove('Collapsible__content--open'); - } else { - content.style.transitionDuration = Math.max(content.scrollHeight, 150) + 'ms'; - content.style.height = content.scrollHeight + 'px'; - content.classList.add('Collapsible__content--open'); - } - }); -})(); diff --git a/docs/theme/arsse/daux.min.js b/docs/theme/arsse/daux.min.js new file mode 100644 index 0000000..fd87588 --- /dev/null +++ b/docs/theme/arsse/daux.min.js @@ -0,0 +1,2 @@ +var e=document.querySelectorAll(".s-content pre"),t=document.querySelector(".CodeToggler"),n="daux_code_blocks_hidden";function a(t){for(var a=0;a code:not(.hljs)");if(l.length){var i=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.async=!0,c.src="".concat(window.base_url,"daux_libraries/highlight.pack.js"),c.onload=function(e){[].forEach.call(l,window.hljs.highlightBlock)},i.appendChild(c)}function s(e){var t=void 0!==e.preventDefault;t&&e.preventDefault();var n=function(e){for(var t=e;(t=t.parentNode)&&9!==t.nodeType;)if(1===t.nodeType&&t.classList.contains("Nav__item"))return t;throw new Error("Could not find a NavItem...")}(e.target),a=n.querySelector("ul.Nav");t&&n.classList.contains("Nav__item--open")?(a.style.height="".concat(a.scrollHeight,"px"),a.style.transitionDuration="150ms",a.style.height="0px",n.classList.remove("Nav__item--open")):t?(a.style.transitionDuration="150ms",a.addEventListener("transitionend",(function e(t){"0px"!==t.target.style.height&&(t.target.style.height="auto"),t.target.removeEventListener("transitionend",e)})),a.style.height="".concat(a.scrollHeight,"px"),n.classList.add("Nav__item--open")):a.style.height="auto"}for(var d,u=document.querySelectorAll(".Nav__item.has-children i.Nav__arrow"),h=u.length-1;h>=0;h--)(d=u[h]).addEventListener("click",s),d.parentNode.parentNode.classList.contains("Nav__item--open")&&s({target:d});var g=document.querySelectorAll(".Nav__item__link--nopage"),v=!0,p=!1,_=void 0;try{for(var y,m=g[Symbol.iterator]();!(v=(y=m.next()).done);v=!0){y.value.addEventListener("click",s)}}catch(e){p=!0,_=e}finally{try{v||null==m.return||m.return()}finally{if(p)throw _}} +//# sourceMappingURL=daux.min.js.map diff --git a/docs/theme/arsse/highlight.pack.js b/docs/theme/arsse/highlight.pack.js deleted file mode 100644 index f1096b4..0000000 --- a/docs/theme/arsse/highlight.pack.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! highlight.js v9.15.10 | BSD3 License | git.io/hljslicense */ -!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"==typeof exports||exports.nodeType?n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs})):e(exports)}(function(a){var f=[],u=Object.keys,N={},c={},n=/^(no-?highlight|plain|text)$/i,s=/\blang(?:uage)?-([\w-]+)\b/i,t=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,r={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},b="",h={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function _(e){return e.replace(/&/g,"&").replace(//g,">")}function E(e){return e.nodeName.toLowerCase()}function v(e,n){var t=e&&e.exec(n);return t&&0===t.index}function l(e){return n.test(e)}function g(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function R(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:"start",offset:t,node:r}),t=e(r,t),E(r).match(/br|hr|img|input/)||a.push({event:"stop",offset:t,node:r}));return t}(e,0),a}function i(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(i)}}function m(o){function s(e){return e&&e.source||e}function c(e,n){return new RegExp(s(e),"m"+(o.cI?"i":"")+(n?"g":""))}!function n(t,e){if(!t.compiled){if(t.compiled=!0,t.k=t.k||t.bK,t.k){function r(t,e){o.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var n=e.split("|");a[n[0]]=[t,n[1]?Number(n[1]):1]})}var a={};"string"==typeof t.k?r("keyword",t.k):u(t.k).forEach(function(e){r(e,t.k[e])}),t.k=a}t.lR=c(t.l||/\w+/,!0),e&&(t.bK&&(t.b="\\b("+t.bK.split(" ").join("|")+")\\b"),t.b||(t.b=/\B|\b/),t.bR=c(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\B|\b/),t.e&&(t.eR=c(t.e)),t.tE=s(t.e)||"",t.eW&&e.tE&&(t.tE+=(t.e?"|":"")+e.tE)),t.i&&(t.iR=c(t.i)),null==t.r&&(t.r=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return function(n){return n.v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return g(n,{v:null},e)})),n.cached_variants||n.eW&&[g(n)]||[n]}("self"===e?t:e)})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e);var i=t.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([t.tE,t.i]).map(s).filter(Boolean);t.t=i.length?c(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i')+n+(t?"":b):n}function o(){E+=null!=l.sL?function(){var e="string"==typeof l.sL;if(e&&!N[l.sL])return _(g);var n=e?C(l.sL,g,!0,f[l.sL]):O(g,l.sL.length?l.sL:void 0);return 0")+'"');return g+=n,n.length||1}var s=B(e);if(!s)throw new Error('Unknown language: "'+e+'"');m(s);var a,l=t||s,f={},E="";for(a=l;a!==s;a=a.parent)a.cN&&(E=c(a.cN,"",!0)+E);var g="",R=0;try{for(var d,p,M=0;l.t.lastIndex=M,d=l.t.exec(n);)p=r(n.substring(M,d.index),d[0]),M=d.index+p;for(r(n.substr(M)),a=l;a.parent;a=a.parent)a.cN&&(E+=b);return{r:R,value:E,language:e,top:l}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:_(n)};throw e}}function O(t,e){e=e||h.languages||u(N);var r={r:0,value:_(t)},a=r;return e.filter(B).filter(M).forEach(function(e){var n=C(e,t,!1);n.language=e,n.r>a.r&&(a=n),n.r>r.r&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function d(e){return h.tabReplace||h.useBR?e.replace(t,function(e,n){return h.useBR&&"\n"===e?"
":h.tabReplace?n.replace(/\t/g,h.tabReplace):""}):e}function o(e){var n,t,r,a,i,o=function(e){var n,t,r,a,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=s.exec(i))return B(t[1])?t[1]:"no-highlight";for(n=0,r=(i=i.split(/\s+/)).length;n/g,"\n"):n=e,i=n.textContent,r=o?C(o,i,!0):O(i),(t=R(n)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=r.value,r.value=function(e,n,t){var r=0,a="",i=[];function o(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){a+=""}function s(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var l=o();if(a+=_(t.substring(r,l[0].offset)),r=l[0].offset,l===e){for(i.reverse().forEach(u);s(l.splice(0,1)[0]),(l=o())===e&&l.length&&l[0].offset===r;);i.reverse().forEach(c)}else"start"===l[0].event?i.push(l[0].node):i.pop(),s(l.splice(0,1)[0])}return a+_(t.substr(r))}(t,R(a),i)),r.value=d(r.value),e.innerHTML=r.value,e.className=function(e,n,t){var r=n?c[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}(e.className,o,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function p(){if(!p.called){p.called=!0;var e=document.querySelectorAll("pre code");f.forEach.call(e,o)}}function B(e){return e=(e||"").toLowerCase(),N[e]||N[c[e]]}function M(e){var n=B(e);return n&&!n.disableAutodetect}return a.highlight=C,a.highlightAuto=O,a.fixMarkup=d,a.highlightBlock=o,a.configure=function(e){h=g(h,e)},a.initHighlighting=p,a.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",p,!1),addEventListener("load",p,!1)},a.registerLanguage=function(n,e){var t=N[n]=e(a);i(t),t.aliases&&t.aliases.forEach(function(e){c[e]=n})},a.listLanguages=function(){return u(N)},a.getLanguage=B,a.autoDetection=M,a.inherit=g,a.IR=a.IDENT_RE="[a-zA-Z]\\w*",a.UIR=a.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",a.NR=a.NUMBER_RE="\\b\\d+(\\.\\d+)?",a.CNR=a.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",a.BNR=a.BINARY_NUMBER_RE="\\b(0b[01]+)",a.RSR=a.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",a.BE=a.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},a.ASM=a.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:"comment",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C("//","$"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C("/\\*","\\*/"),a.HCM=a.HASH_COMMENT_MODE=a.C("#","$"),a.NM=a.NUMBER_MODE={cN:"number",b:a.NR,r:0},a.CNM=a.C_NUMBER_MODE={cN:"number",b:a.CNR,r:0},a.BNM=a.BINARY_NUMBER_MODE={cN:"number",b:a.BNR,r:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:"number",b:a.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},a.RM=a.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[a.BE,{b:/\[/,e:/\]/,r:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:"title",b:a.IR,r:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:"title",b:a.UIR,r:0},a.METHOD_GUARD={b:"\\.\\s*"+a.UIR,r:0},a});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,{cN:"",b:/\\"/},{cN:"string",b:/'/,e:/'/},t]}});hljs.registerLanguage("shell",function(s){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:["php","php3","php4","php5","php6","php7"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,t,a]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},t,a]}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("xml",function(s){var e={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("\x3c!--","--\x3e",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"meta",b:/<\?xml/,e:/\?>/,r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0},{b:'b"',e:'"',skip:!0},{b:"b'",e:"'",skip:!0},s.inherit(s.ASM,{i:null,cN:null,c:null,skip:!0}),s.inherit(s.QSM,{i:null,cN:null,c:null,skip:!0})]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[e],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[e],starts:{e:"<\/script>",rE:!0,sL:["actionscript","javascript","handlebars","xml","vbscript"]}},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},e]}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}}); \ No newline at end of file diff --git a/docs/theme/src/arsse.scss b/docs/theme/src/arsse.scss index 6f6f8c6..43a26c1 100644 --- a/docs/theme/src/arsse.scss +++ b/docs/theme/src/arsse.scss @@ -1,12 +1,12 @@ /* Daux imports; fonts are omitted */ -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/vendor/normalize.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_variables.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_mixins.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_structure.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_typography.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_components.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_homepage.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_print.scss" print; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/vendor/normalize.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_variables.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_mixins.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_structure.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_typography.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_components.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_homepage.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_print.scss" print; diff --git a/vendor-bin/daux/composer.json b/vendor-bin/daux/composer.json index 99a71b3..723bdf0 100644 --- a/vendor-bin/daux/composer.json +++ b/vendor-bin/daux/composer.json @@ -1,5 +1,5 @@ { "require": { - "daux/daux.io": "^0.10.1" + "daux/daux.io": "^0.11" } } diff --git a/vendor-bin/daux/composer.lock b/vendor-bin/daux/composer.lock index 860913b..d2befae 100644 --- a/vendor-bin/daux/composer.lock +++ b/vendor-bin/daux/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c53b1115bf13a026ec792e74b04fe703", + "content-hash": "6d944ffdc165b3e6f14e71a82b67a57d", "packages": [ { "name": "daux/daux.io", - "version": "0.10.1", + "version": "0.11.1", "source": { "type": "git", "url": "https://github.com/dauxio/daux.io.git", - "reference": "298eef8f9c4d4d380f5e7beb5472b4bff80566d0" + "reference": "e796fad8627b7a2c95d1caf80e8e7b19969133e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dauxio/daux.io/zipball/298eef8f9c4d4d380f5e7beb5472b4bff80566d0", - "reference": "298eef8f9c4d4d380f5e7beb5472b4bff80566d0", + "url": "https://api.github.com/repos/dauxio/daux.io/zipball/e796fad8627b7a2c95d1caf80e8e7b19969133e9", + "reference": "e796fad8627b7a2c95d1caf80e8e7b19969133e9", "shasum": "" }, "require": { @@ -26,6 +26,7 @@ "league/plates": "~3.1", "myclabs/deep-copy": "^1.5", "php": ">=7.1.3", + "scrivo/highlight.php": "^9.15", "symfony/console": "^4.0", "symfony/http-foundation": "^4.0", "symfony/polyfill-intl-icu": "^1.10", @@ -74,7 +75,7 @@ "markdown", "md" ], - "time": "2019-08-28T13:42:34+00:00" + "time": "2019-09-23T20:10:07+00:00" }, { "name": "guzzlehttp/guzzle", @@ -574,18 +575,85 @@ "description": "A polyfill for getallheaders.", "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "scrivo/highlight.php", + "version": "v9.15.10.0", + "source": { + "type": "git", + "url": "https://github.com/scrivo/highlight.php.git", + "reference": "9ad3adb4456dc91196327498dbbce6aa1ba1239e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/9ad3adb4456dc91196327498dbbce6aa1ba1239e", + "reference": "9ad3adb4456dc91196327498dbbce6aa1ba1239e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.7", + "symfony/finder": "^2.8" + }, + "suggest": { + "ext-dom": "Needed to make use of the features in the utilities namespace" + }, + "type": "library", + "autoload": { + "psr-0": { + "Highlight\\": "", + "HighlightUtilities\\": "" + }, + "files": [ + "HighlightUtilities/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Geert Bergman", + "homepage": "http://www.scrivo.org/", + "role": "Project Author" + }, + { + "name": "Vladimir Jimenez", + "homepage": "https://allejo.io", + "role": "Contributor" + }, + { + "name": "Martin Folkers", + "homepage": "https://twobrain.io", + "role": "Contributor" + } + ], + "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js", + "keywords": [ + "code", + "highlight", + "highlight.js", + "highlight.php", + "syntax" + ], + "time": "2019-08-27T04:27:48+00:00" + }, { "name": "symfony/console", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "de63799239b3881b8a08f8481b22348f77ed7b36" + "reference": "929ddf360d401b958f611d44e726094ab46a7369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/de63799239b3881b8a08f8481b22348f77ed7b36", - "reference": "de63799239b3881b8a08f8481b22348f77ed7b36", + "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", + "reference": "929ddf360d401b958f611d44e726094ab46a7369", "shasum": "" }, "require": { @@ -647,20 +715,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:26:39+00:00" + "time": "2019-10-07T12:36:49+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "d804bea118ff340a12e22a79f9c7e7eb56b35adc" + "reference": "76590ced16d4674780863471bae10452b79210a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d804bea118ff340a12e22a79f9c7e7eb56b35adc", - "reference": "d804bea118ff340a12e22a79f9c7e7eb56b35adc", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/76590ced16d4674780863471bae10452b79210a5", + "reference": "76590ced16d4674780863471bae10452b79210a5", "shasum": "" }, "require": { @@ -702,20 +770,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:55:16+00:00" + "time": "2019-10-04T19:48:13+00:00" }, { "name": "symfony/intl", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "8db5505703c5bdb23d524fd994dad2f781966538" + "reference": "818771ff6acef04cdce05023ddfc39b7078014bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/8db5505703c5bdb23d524fd994dad2f781966538", - "reference": "8db5505703c5bdb23d524fd994dad2f781966538", + "url": "https://api.github.com/repos/symfony/intl/zipball/818771ff6acef04cdce05023ddfc39b7078014bf", + "reference": "818771ff6acef04cdce05023ddfc39b7078014bf", "shasum": "" }, "require": { @@ -777,20 +845,20 @@ "l10n", "localization" ], - "time": "2019-08-26T08:26:39+00:00" + "time": "2019-10-04T21:18:34+00:00" }, { "name": "symfony/mime", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "987a05df1c6ac259b34008b932551353f4f408df" + "reference": "32f71570547b91879fdbd9cf50317d556ae86916" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/987a05df1c6ac259b34008b932551353f4f408df", - "reference": "987a05df1c6ac259b34008b932551353f4f408df", + "url": "https://api.github.com/repos/symfony/mime/zipball/32f71570547b91879fdbd9cf50317d556ae86916", + "reference": "32f71570547b91879fdbd9cf50317d556ae86916", "shasum": "" }, "require": { @@ -836,7 +904,7 @@ "mime", "mime-type" ], - "time": "2019-08-22T08:16:11+00:00" + "time": "2019-09-19T17:00:15+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1190,16 +1258,16 @@ }, { "name": "symfony/process", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e89969c00d762349f078db1128506f7f3dcc0d4a" + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e89969c00d762349f078db1128506f7f3dcc0d4a", - "reference": "e89969c00d762349f078db1128506f7f3dcc0d4a", + "url": "https://api.github.com/repos/symfony/process/zipball/50556892f3cc47d4200bfd1075314139c4c9ff4b", + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b", "shasum": "" }, "require": { @@ -1235,20 +1303,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:26:39+00:00" + "time": "2019-09-26T21:17:10+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.6", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3" + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ea7263d6b6d5f798b56a45a5b8d686725f2719a3", - "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0", + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0", "shasum": "" }, "require": { @@ -1293,20 +1361,20 @@ "interoperability", "standards" ], - "time": "2019-08-20T14:44:19+00:00" + "time": "2019-09-17T11:12:18+00:00" }, { "name": "symfony/yaml", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "5a0b7c32dc3ec56fd4abae8a4a71b0cf05013686" + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/5a0b7c32dc3ec56fd4abae8a4a71b0cf05013686", - "reference": "5a0b7c32dc3ec56fd4abae8a4a71b0cf05013686", + "url": "https://api.github.com/repos/symfony/yaml/zipball/41e16350a2a1c7383c4735aa2f9fce74cf3d1178", + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178", "shasum": "" }, "require": { @@ -1352,7 +1420,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-08-20T14:27:59+00:00" + "time": "2019-09-11T15:41:19+00:00" }, { "name": "webuni/commonmark-table-extension", From 5d70f9fc11fcb43c275cc374f6be7b85c6ca204f Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 11 Oct 2019 12:02:22 -0400 Subject: [PATCH 02/20] Update dependencies --- composer.lock | 11 +- vendor-bin/csfixer/composer.lock | 229 ++++++++++++++++--------------- vendor-bin/phpunit/composer.lock | 181 ++++++++++++------------ vendor-bin/robo/composer.lock | 134 +++++++++--------- 4 files changed, 278 insertions(+), 277 deletions(-) diff --git a/composer.lock b/composer.lock index 54a7444..c33f781 100644 --- a/composer.lock +++ b/composer.lock @@ -347,16 +347,16 @@ }, { "name": "zendframework/zend-diactoros", - "version": "2.1.3", + "version": "2.1.5", "source": { "type": "git", "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "279723778c40164bcf984a2df12ff2c6ec5e61c1" + "reference": "6dcf9e760a6b476f3e9d80abbc9ce9c4aa921f9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/279723778c40164bcf984a2df12ff2c6ec5e61c1", - "reference": "279723778c40164bcf984a2df12ff2c6ec5e61c1", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/6dcf9e760a6b476f3e9d80abbc9ce9c4aa921f9c", + "reference": "6dcf9e760a6b476f3e9d80abbc9ce9c4aa921f9c", "shasum": "" }, "require": { @@ -369,6 +369,7 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { + "ext-curl": "*", "ext-dom": "*", "ext-libxml": "*", "http-interop/http-factory-tests": "^0.5.0", @@ -409,7 +410,7 @@ "psr", "psr-7" ], - "time": "2019-07-10T16:13:25+00:00" + "time": "2019-10-10T17:38:20+00:00" }, { "name": "zendframework/zend-httphandlerrunner", diff --git a/vendor-bin/csfixer/composer.lock b/vendor-bin/csfixer/composer.lock index faa225f..9344759 100644 --- a/vendor-bin/csfixer/composer.lock +++ b/vendor-bin/csfixer/composer.lock @@ -114,16 +114,16 @@ }, { "name": "doctrine/annotations", - "version": "v1.6.1", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", "shasum": "" }, "require": { @@ -132,12 +132,12 @@ }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^7.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -150,6 +150,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -158,10 +162,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -178,32 +178,34 @@ "docblock", "parser" ], - "time": "2019-03-25T19:12:02+00:00" + "time": "2019-10-01T18:55:10+00:00" }, { "name": "doctrine/lexer", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e17f069ede36f7534b95adec71910ed1b49c74ea", + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -216,14 +218,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -238,20 +240,20 @@ "parser", "php" ], - "time": "2019-06-08T11:03:04+00:00" + "time": "2019-07-30T19:33:28+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.15.1", + "version": "v2.15.3", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "20064511ab796593a3990669eff5f5b535001f7c" + "reference": "705490b0f282f21017d73561e9498d2b622ee34c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/20064511ab796593a3990669eff5f5b535001f7c", - "reference": "20064511ab796593a3990669eff5f5b535001f7c", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/705490b0f282f21017d73561e9498d2b622ee34c", + "reference": "705490b0f282f21017d73561e9498d2b622ee34c", "shasum": "" }, "require": { @@ -281,9 +283,10 @@ "php-cs-fixer/accessible-object": "^1.0", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1", "phpunitgoodpractices/traits": "^1.8", - "symfony/phpunit-bridge": "^4.3" + "symfony/phpunit-bridge": "^4.3", + "symfony/yaml": "^3.0 || ^4.0" }, "suggest": { "ext-mbstring": "For handling non-UTF8 characters in cache signature.", @@ -316,17 +319,17 @@ "MIT" ], "authors": [ - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" } ], "description": "A tool to automatically fix PHP code style", - "time": "2019-06-01T10:32:12+00:00" + "time": "2019-08-31T12:51:54+00:00" }, { "name": "paragonie/random_compat", @@ -522,16 +525,16 @@ }, { "name": "symfony/console", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39" + "reference": "929ddf360d401b958f611d44e726094ab46a7369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b592b26a24265a35172d8a2094d8b10f22b7cc39", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39", + "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", + "reference": "929ddf360d401b958f611d44e726094ab46a7369", "shasum": "" }, "require": { @@ -593,20 +596,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-07T12:36:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398" + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d257021c1ab28d48d24a16de79dfab445ce93398", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", "shasum": "" }, "require": { @@ -663,20 +666,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-01T16:40:32+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c" + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c61766f4440ca687de1084a5c00b08e167a2575c", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", "shasum": "" }, "require": { @@ -721,20 +724,20 @@ "interoperability", "standards" ], - "time": "2019-06-20T06:46:26+00:00" + "time": "2019-09-17T09:54:03+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/9abbb7ef96a51f4d7e69627bc6f63307994e4263", + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263", "shasum": "" }, "require": { @@ -771,20 +774,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-23T08:51:25+00:00" + "time": "2019-08-20T14:07:54+00:00" }, { "name": "symfony/finder", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1", + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1", "shasum": "" }, "require": { @@ -820,20 +823,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-09-16T11:29:48+00:00" }, { "name": "symfony/options-resolver", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "40762ead607c8f792ee4516881369ffa553fee6f" + "reference": "81c2e120522a42f623233968244baebd6b36cb6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/40762ead607c8f792ee4516881369ffa553fee6f", - "reference": "40762ead607c8f792ee4516881369ffa553fee6f", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/81c2e120522a42f623233968244baebd6b36cb6a", + "reference": "81c2e120522a42f623233968244baebd6b36cb6a", "shasum": "" }, "require": { @@ -874,20 +877,20 @@ "configuration", "options" ], - "time": "2019-06-13T11:01:17+00:00" + "time": "2019-08-08T09:29:19+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -899,7 +902,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -916,12 +919,12 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -932,20 +935,20 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -957,7 +960,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -991,20 +994,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "bc4858fb611bda58719124ca079baff854149c89" + "reference": "54b4c428a0054e254223797d2713c31e08610831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", - "reference": "bc4858fb611bda58719124ca079baff854149c89", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/54b4c428a0054e254223797d2713c31e08610831", + "reference": "54b4c428a0054e254223797d2713c31e08610831", "shasum": "" }, "require": { @@ -1014,7 +1017,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1050,20 +1053,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" + "reference": "04ce3335667451138df4307d6a9b61565560199e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e", + "reference": "04ce3335667451138df4307d6a9b61565560199e", "shasum": "" }, "require": { @@ -1072,7 +1075,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1105,20 +1108,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd" + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", "shasum": "" }, "require": { @@ -1127,7 +1130,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1163,20 +1166,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/process", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c" + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/856d35814cf287480465bb7a6c413bb7f5f5e69c", - "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c", + "url": "https://api.github.com/repos/symfony/process/zipball/50556892f3cc47d4200bfd1075314139c4c9ff4b", + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b", "shasum": "" }, "require": { @@ -1212,20 +1215,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-09-26T21:17:10+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0", + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0", "shasum": "" }, "require": { @@ -1270,20 +1273,20 @@ "interoperability", "standards" ], - "time": "2019-06-13T11:15:36+00:00" + "time": "2019-09-17T11:12:18+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "6b100e9309e8979cf1978ac1778eb155c1f7d93b" + "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6b100e9309e8979cf1978ac1778eb155c1f7d93b", - "reference": "6b100e9309e8979cf1978ac1778eb155c1f7d93b", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/1e4ff456bd625be5032fac9be4294e60442e9b71", + "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71", "shasum": "" }, "require": { @@ -1320,7 +1323,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2019-05-27T08:16:38+00:00" + "time": "2019-08-07T11:52:19+00:00" } ], "packages-dev": [], diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index e27b08c..558318c 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -114,23 +114,23 @@ }, { "name": "mikey179/vfsstream", - "version": "v1.6.6", + "version": "v1.6.7", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", - "reference": "095238a0711c974ae5b4ebf4c4534a23f3f6c99d" + "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/095238a0711c974ae5b4ebf4c4534a23f3f6c99d", - "reference": "095238a0711c974ae5b4ebf4c4534a23f3f6c99d", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb", + "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "~4.5" + "phpunit/phpunit": "^4.5|^5.0" }, "type": "library", "extra": { @@ -156,20 +156,20 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2019-04-08T13:54:32+00:00" + "time": "2019-08-01T01:38:37+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.1", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", "shasum": "" }, "require": { @@ -204,7 +204,7 @@ "object", "object graph" ], - "time": "2019-04-07T13:18:21+00:00" + "time": "2019-08-09T12:45:53+00:00" }, { "name": "phake/phake", @@ -368,35 +368,33 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "~6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -418,30 +416,30 @@ "reflection", "static analysis" ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2018-08-07T13:53:10+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.1", + "version": "4.3.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", "shasum": "" }, "require": { "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", "webmozart/assert": "^1.0" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", + "doctrine/instantiator": "^1.0.5", "mockery/mockery": "^1.0", "phpunit/phpunit": "^6.4" }, @@ -469,41 +467,40 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-04-30T17:48:53+00:00" + "time": "2019-09-12T14:27:41+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -516,26 +513,27 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" }, { "name": "phpspec/prophecy", - "version": "1.8.1", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, @@ -579,7 +577,7 @@ "spy", "stub" ], - "time": "2019-06-13T12:50:23+00:00" + "time": "2019-10-03T11:07:50+00:00" }, { "name": "phpunit/php-code-coverage", @@ -786,16 +784,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.0.2", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c" + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", - "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", "shasum": "" }, "require": { @@ -808,7 +806,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -831,20 +829,20 @@ "keywords": [ "tokenizer" ], - "time": "2019-07-08T05:24:54+00:00" + "time": "2019-09-17T06:23:10+00:00" }, { "name": "phpunit/phpunit", - "version": "7.5.14", + "version": "7.5.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2834789aeb9ac182ad69bfdf9ae91856a59945ff" + "reference": "316afa6888d2562e04aeb67ea7f2017a0eb41661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2834789aeb9ac182ad69bfdf9ae91856a59945ff", - "reference": "2834789aeb9ac182ad69bfdf9ae91856a59945ff", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/316afa6888d2562e04aeb67ea7f2017a0eb41661", + "reference": "316afa6888d2562e04aeb67ea7f2017a0eb41661", "shasum": "" }, "require": { @@ -904,8 +902,8 @@ "authors": [ { "name": "Sebastian Bergmann", - "role": "lead", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], "description": "The PHP Unit Testing framework.", @@ -915,7 +913,7 @@ "testing", "xunit" ], - "time": "2019-07-15T06:24:08+00:00" + "time": "2019-09-14T09:08:39+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1137,16 +1135,16 @@ }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", "shasum": "" }, "require": { @@ -1173,6 +1171,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1181,17 +1183,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -1200,7 +1198,7 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2019-09-14T09:02:43+00:00" }, { "name": "sebastian/global-state", @@ -1485,16 +1483,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -1506,7 +1504,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1523,12 +1521,12 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -1539,7 +1537,7 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "theseer/tokenizer", @@ -1583,16 +1581,16 @@ }, { "name": "webmozart/assert", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", "shasum": "" }, "require": { @@ -1600,8 +1598,7 @@ "symfony/polyfill-ctype": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", "extra": { @@ -1630,7 +1627,7 @@ "check", "validate" ], - "time": "2018-12-25T11:19:39+00:00" + "time": "2019-08-24T08:43:50+00:00" }, { "name": "webmozart/glob", diff --git a/vendor-bin/robo/composer.lock b/vendor-bin/robo/composer.lock index 33c71e2..6ebab02 100644 --- a/vendor-bin/robo/composer.lock +++ b/vendor-bin/robo/composer.lock @@ -376,16 +376,16 @@ }, { "name": "consolidation/robo", - "version": "1.4.9", + "version": "1.4.10", "source": { "type": "git", "url": "https://github.com/consolidation/Robo.git", - "reference": "5c6b3840a45afda1cbffbb3bb1f94dd5f9f83345" + "reference": "e5a6ca64cf1324151873672e484aceb21f365681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/Robo/zipball/5c6b3840a45afda1cbffbb3bb1f94dd5f9f83345", - "reference": "5c6b3840a45afda1cbffbb3bb1f94dd5f9f83345", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/e5a6ca64cf1324151873672e484aceb21f365681", + "reference": "e5a6ca64cf1324151873672e484aceb21f365681", "shasum": "" }, "require": { @@ -480,7 +480,7 @@ } ], "description": "Modern task runner", - "time": "2019-03-19T18:07:19+00:00" + "time": "2019-07-29T15:40:50+00:00" }, { "name": "consolidation/self-update", @@ -1092,16 +1092,16 @@ }, { "name": "symfony/console", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39" + "reference": "929ddf360d401b958f611d44e726094ab46a7369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b592b26a24265a35172d8a2094d8b10f22b7cc39", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39", + "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", + "reference": "929ddf360d401b958f611d44e726094ab46a7369", "shasum": "" }, "require": { @@ -1163,20 +1163,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-07T12:36:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398" + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d257021c1ab28d48d24a16de79dfab445ce93398", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", "shasum": "" }, "require": { @@ -1233,20 +1233,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-01T16:40:32+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c" + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c61766f4440ca687de1084a5c00b08e167a2575c", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", "shasum": "" }, "require": { @@ -1291,20 +1291,20 @@ "interoperability", "standards" ], - "time": "2019-06-20T06:46:26+00:00" + "time": "2019-09-17T09:54:03+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/9abbb7ef96a51f4d7e69627bc6f63307994e4263", + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263", "shasum": "" }, "require": { @@ -1341,20 +1341,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-23T08:51:25+00:00" + "time": "2019-08-20T14:07:54+00:00" }, { "name": "symfony/finder", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1", + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1", "shasum": "" }, "require": { @@ -1390,20 +1390,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-09-16T11:29:48+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -1415,7 +1415,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1432,12 +1432,12 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -1448,20 +1448,20 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -1473,7 +1473,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1507,20 +1507,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd" + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", "shasum": "" }, "require": { @@ -1529,7 +1529,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1565,20 +1565,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/process", - "version": "v3.4.29", + "version": "v3.4.32", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d129c017e8602507688ef2c3007951a16c1a8407" + "reference": "344dc588b163ff58274f1769b90b75237f32ed16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d129c017e8602507688ef2c3007951a16c1a8407", - "reference": "d129c017e8602507688ef2c3007951a16c1a8407", + "url": "https://api.github.com/repos/symfony/process/zipball/344dc588b163ff58274f1769b90b75237f32ed16", + "reference": "344dc588b163ff58274f1769b90b75237f32ed16", "shasum": "" }, "require": { @@ -1614,20 +1614,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-05-30T15:47:52+00:00" + "time": "2019-09-25T14:09:38+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0", + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0", "shasum": "" }, "require": { @@ -1672,20 +1672,20 @@ "interoperability", "standards" ], - "time": "2019-06-13T11:15:36+00:00" + "time": "2019-09-17T11:12:18+00:00" }, { "name": "symfony/yaml", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99" + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/c60ecf5ba842324433b46f58dc7afc4487dbab99", - "reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99", + "url": "https://api.github.com/repos/symfony/yaml/zipball/41e16350a2a1c7383c4735aa2f9fce74cf3d1178", + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178", "shasum": "" }, "require": { @@ -1731,7 +1731,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-04-06T14:04:46+00:00" + "time": "2019-09-11T15:41:19+00:00" } ], "packages-dev": [], From cf5c08459f7b0d7b8fd0f0a6f961a1de6e532e95 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 11 Oct 2019 12:51:32 -0400 Subject: [PATCH 03/20] Remove unused Daux libs --- RoboFile.php | 1 + 1 file changed, 1 insertion(+) diff --git a/RoboFile.php b/RoboFile.php index 0bb505a..23cd78a 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -196,6 +196,7 @@ class RoboFile extends \Robo\Tasks { $execpath = escapeshellarg(norm(BASE."vendor/bin/daux")); $t = $this->collectionBuilder(); $t->taskExec($execpath)->arg("generate")->option("-d", BASE."manual")->args($args); + $t->taskDeleteDir(BASE."manual/daux_libraries"); $t->taskDeleteDir(BASE."manual/theme"); $t->taskDeleteDir(BASE."manual/themes/src"); return $t->run(); From cb1039326c944265557d93693ea09dc55a56e1fe Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 11 Oct 2019 13:04:15 -0400 Subject: [PATCH 04/20] Fix PostgreSQL tests when using "trust" authentication --- tests/cases/Db/PostgreSQL/TestCreation.php | 2 +- tests/cases/Db/PostgreSQLPDO/TestCreation.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/Db/PostgreSQL/TestCreation.php b/tests/cases/Db/PostgreSQL/TestCreation.php index 720e32b..cbc7fb2 100644 --- a/tests/cases/Db/PostgreSQL/TestCreation.php +++ b/tests/cases/Db/PostgreSQL/TestCreation.php @@ -65,7 +65,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // we cannnot distinguish between different connection failure modes self::setConf([ - 'dbPostgreSQLPass' => (string) rand(), + 'dbPostgreSQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; diff --git a/tests/cases/Db/PostgreSQLPDO/TestCreation.php b/tests/cases/Db/PostgreSQLPDO/TestCreation.php index a9babc1..5e2ad7b 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestCreation.php +++ b/tests/cases/Db/PostgreSQLPDO/TestCreation.php @@ -65,7 +65,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // PDO dies not distinguish between different connection failure modes self::setConf([ - 'dbPostgreSQLPass' => (string) rand(), + 'dbPostgreSQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; From b8b8a6aa70efb0fbe509d83b7c24ca7828f575e9 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Wed, 16 Oct 2019 10:26:39 -0400 Subject: [PATCH 05/20] Also adjust test for MySQL connection failure --- tests/cases/Db/MySQL/TestCreation.php | 2 +- tests/cases/Db/MySQLPDO/TestCreation.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/Db/MySQL/TestCreation.php b/tests/cases/Db/MySQL/TestCreation.php index 823a5a3..5283458 100644 --- a/tests/cases/Db/MySQL/TestCreation.php +++ b/tests/cases/Db/MySQL/TestCreation.php @@ -22,7 +22,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // for the sake of simplicity we don't distinguish between failure modes, but the MySQL-supplied error messages do self::setConf([ - 'dbMySQLPass' => (string) rand(), + 'dbMySQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; diff --git a/tests/cases/Db/MySQLPDO/TestCreation.php b/tests/cases/Db/MySQLPDO/TestCreation.php index 5ca4e7d..aa9b849 100644 --- a/tests/cases/Db/MySQLPDO/TestCreation.php +++ b/tests/cases/Db/MySQLPDO/TestCreation.php @@ -22,7 +22,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // for the sake of simplicity we don't distinguish between failure modes, but the MySQL-supplied error messages do self::setConf([ - 'dbMySQLPass' => (string) rand(), + 'dbMySQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; From 64c3ec3571584d9bc17cdd0e2cf219508c475e61 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Thu, 17 Oct 2019 13:00:56 -0400 Subject: [PATCH 06/20] Coverage fixes and OPML bugfix --- CHANGELOG | 1 + RoboFile.php | 6 ++++-- lib/CLI.php | 4 ++-- lib/ImportExport/AbstractImportExport.php | 8 ++++---- lib/REST/Fever/API.php | 3 ++- tests/cases/ImportExport/TestImportExport.php | 2 ++ .../Lang/{testComplex.php => TestComplex.php} | 0 tests/lib/Lang/Setup.php | 6 +++++- tests/lib/Lang/TestLang.php | 15 --------------- 9 files changed, 20 insertions(+), 25 deletions(-) rename tests/cases/Lang/{testComplex.php => TestComplex.php} (100%) delete mode 100644 tests/lib/Lang/TestLang.php diff --git a/CHANGELOG b/CHANGELOG index 3e48ece..5448364 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Version 0.8.1 (2019-??-??) Bug fixes: - Don't crash updating feeds cached solely via ETag +- Don't fail importing new folders from OPML files - Don't fail adding a feed which collides with another via redirection - Don't fail on very long text-search queries containing question marks when using PostgreSQL or MySQL diff --git a/RoboFile.php b/RoboFile.php index 23cd78a..f382090 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -5,6 +5,7 @@ use Robo\Result; const BASE = __DIR__.\DIRECTORY_SEPARATOR; const BASE_TEST = BASE."tests".\DIRECTORY_SEPARATOR; define("IS_WIN", defined("PHP_WINDOWS_VERSION_MAJOR")); +define("IS_MAC", php_uname("s") === "Darwin"); function norm(string $path): string { $out = realpath($path); @@ -92,12 +93,13 @@ class RoboFile extends \Robo\Tasks { $dbg = dirname(\PHP_BINARY)."\\phpdbg.exe"; $dbg = file_exists($dbg) ? $dbg : ""; } else { - $dbg = trim(`which phpdbg`); + $dbg = trim(`which phpdbg 2>/dev/null`); } if ($dbg) { return escapeshellarg($dbg)." -qrr"; } else { - return escapeshellarg(\PHP_BINARY); + $ext = IS_WIN ? "dll" : (IS_MAC ? "dylib" : "so"); + return escapeshellarg(\PHP_BINARY)." -d zend_extension=xdebug.$ext"; } } diff --git a/lib/CLI.php b/lib/CLI.php index bbd9930..702b9f5 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -206,7 +206,7 @@ USAGE_TEXT; $this->logError($e->getMessage()); return $e->getCode(); } - } + } // @codeCoverageIgnore /** @codeCoverageIgnore */ protected function logError(string $msg) { @@ -248,7 +248,7 @@ USAGE_TEXT; case "": return $this->userList(); } - } + } // @codeCoverageIgnore protected function userAddOrSetPassword(string $method, string $user, string $password = null, string $oldpass = null): int { $passwd = Arsse::$user->$method(...array_slice(func_get_args(), 1)); diff --git a/lib/ImportExport/AbstractImportExport.php b/lib/ImportExport/AbstractImportExport.php index f882ea1..19fa5fc 100644 --- a/lib/ImportExport/AbstractImportExport.php +++ b/lib/ImportExport/AbstractImportExport.php @@ -57,7 +57,7 @@ abstract class AbstractImportExport { } if (!isset($folderMap[$id])) { // if no existing folder exists, add one - $folderMap[$id] = Arsse::$db->folderAdd($user, ['name' => $f['name'], 'parent' -> $parent]); + $folderMap[$id] = Arsse::$db->folderAdd($user, ['name' => $f['name'], 'parent' => $parent]); } } // process newsfeed subscriptions @@ -118,21 +118,21 @@ abstract class AbstractImportExport { foreach (array_diff(array_column($feedsDb, "id"), $feedMap) as $id) { try { Arsse::$db->subscriptionRemove($user, $id); - } catch (InputException $e) { + } catch (InputException $e) { // @codeCoverageIgnore // ignore errors } } foreach (array_diff(array_column($foldersDb, "id"), $folderMap) as $id) { try { Arsse::$db->folderRemove($user, $id); - } catch (InputException $e) { + } catch (InputException $e) { // @codeCoverageIgnore // ignore errors } } foreach (array_diff(array_column($tagsDb, "name"), array_keys($tagMap)) as $id) { try { Arsse::$db->tagRemove($user, $id, true); - } catch (InputException $e) { + } catch (InputException $e) { // @codeCoverageIgnore // ignore errors } } diff --git a/lib/REST/Fever/API.php b/lib/REST/Fever/API.php index 1401d63..ac85aa8 100644 --- a/lib/REST/Fever/API.php +++ b/lib/REST/Fever/API.php @@ -207,7 +207,8 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // indexed arrays $p->appendChild($this->makeXMLIndexed($v, $d->createElement($k), substr($k, 0, strlen($k) - 1))); } else { - $p->appendChild($this->makeXMLAssoc($v, $d->createElement($k))); + // this case does not actually occur in a proper Fever response + $p->appendChild($this->makeXMLAssoc($v, $d->createElement($k))); // @codeCoverageIgnore } } return $p; diff --git a/tests/cases/ImportExport/TestImportExport.php b/tests/cases/ImportExport/TestImportExport.php index c8af2c1..6c7de1f 100644 --- a/tests/cases/ImportExport/TestImportExport.php +++ b/tests/cases/ImportExport/TestImportExport.php @@ -212,11 +212,13 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['id' => 4, 'name' => "Politics", 'parent' => 0], ['id' => 5, 'name' => "Local", 'parent' => 4], ['id' => 6, 'name' => "National", 'parent' => 4], + ['id' => 7, 'name' => "Nature", 'parent' => 0], // new folder ]]; \Phake::when($this->proc)->parse->thenReturn($in); $this->proc->import("john.doe@example.com", "", false, true); $exp = $this->primeExpectations($this->data, $this->checkTables); $exp['arsse_subscriptions']['rows'][3] = [4, "john.doe@example.com", null, 4, "CBC"]; + $exp['arsse_folders']['rows'][] = [7, "john.doe@example.com", null, "Nature"]; $this->compareExpectations($this->drv, $exp); } diff --git a/tests/cases/Lang/testComplex.php b/tests/cases/Lang/TestComplex.php similarity index 100% rename from tests/cases/Lang/testComplex.php rename to tests/cases/Lang/TestComplex.php diff --git a/tests/lib/Lang/Setup.php b/tests/lib/Lang/Setup.php index 381806f..e70ccb0 100644 --- a/tests/lib/Lang/Setup.php +++ b/tests/lib/Lang/Setup.php @@ -9,6 +9,7 @@ namespace JKingWeb\Arsse\Test\Lang; use JKingWeb\Arsse\Lang; use JKingWeb\Arsse\Arsse; use org\bovigo\vfs\vfsStream; +use Webmozart\Glob\Glob; trait Setup { public function setUp() { @@ -36,7 +37,10 @@ trait Setup { // set up a file without read access chmod($this->path."ru.php", 0000); // make the test Lang class use the vfs files - $this->l = new TestLang($this->path); + $this->l = \Phake::partialMock(Lang::class, $this->path); + \Phake::when($this->l)->globFiles->thenReturnCallback(function(string $path): array { + return Glob::glob($this->path."*.php"); + }); // create a mock Lang object so as not to create a dependency loop self::clearData(false); Arsse::$lang = \Phake::mock(Lang::class); diff --git a/tests/lib/Lang/TestLang.php b/tests/lib/Lang/TestLang.php deleted file mode 100644 index 3022535..0000000 --- a/tests/lib/Lang/TestLang.php +++ /dev/null @@ -1,15 +0,0 @@ -path."*.php"); - } -} From c3643fba10c350e83f69843eed3f1263c45a1cbf Mon Sep 17 00:00:00 2001 From: "J. King" Date: Thu, 17 Oct 2019 16:23:41 -0400 Subject: [PATCH 07/20] Tests for URL::absolute() --- tests/cases/Misc/TestURL.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/cases/Misc/TestURL.php b/tests/cases/Misc/TestURL.php index 8260c0b..e045d30 100644 --- a/tests/cases/Misc/TestURL.php +++ b/tests/cases/Misc/TestURL.php @@ -91,4 +91,21 @@ class TestURL extends \JKingWeb\Arsse\Test\AbstractTest { ["/#ack", "", "/#ack"], ]; } + + /** @dataProvider provideAbsolutes */ + public function testDetermineAbsoluteness(bool $exp, string $url) { + $this->assertSame($exp, URL::absolute($url)); + } + + public function provideAbsolutes() { + return [ + [true, "http://example.com/"], + [true, "HTTP://example.com/"], + [false, "//example.com/"], + [false, "/example"], + [false, "example.com/"], + [false, "example.com"], + [false, "http:///example"], + ]; + } } From c706a76057f36aaac22c30ed3f4657e593f8ae80 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 18 Oct 2019 13:10:03 -0400 Subject: [PATCH 08/20] Simplify array flattening --- lib/Db/AbstractStatement.php | 45 +++++++++++------------------- lib/Misc/ValueInfo.php | 11 ++++++++ tests/cases/Misc/TestValueInfo.php | 6 ++++ 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/lib/Db/AbstractStatement.php b/lib/Db/AbstractStatement.php index cc8ce42..8471986 100644 --- a/lib/Db/AbstractStatement.php +++ b/lib/Db/AbstractStatement.php @@ -46,23 +46,14 @@ abstract class AbstractStatement implements Statement { return $query; } - public function retypeArray(array $bindings, bool $append = false): bool { - if (!$append) { - $this->types = []; - } - foreach ($bindings as $binding) { - if (is_array($binding)) { - // recursively flatten any arrays, which may be provided for SET or IN() clauses - $this->retypeArray($binding, true); - } else { - $bindId = self::TYPES[trim(strtolower($binding))] ?? 0; - assert($bindId, new Exception("paramTypeInvalid", $binding)); - $this->types[] = $bindId; - } - } - if (!$append) { - $this->prepare(static::mungeQuery($this->query, $this->types)); + public function retypeArray(array $bindings): bool { + $this->types = []; + foreach (ValueInfo::flatten($bindings) as $binding) { // recursively flatten any arrays, which may be provided for SET or IN() clauses + $bindId = self::TYPES[trim(strtolower($binding))] ?? 0; + assert($bindId, new Exception("paramTypeInvalid", $binding)); + $this->types[] = $bindId; } + $this->prepare(static::mungeQuery($this->query, $this->types)); return true; } @@ -79,26 +70,22 @@ abstract class AbstractStatement implements Statement { } } - protected function bindValues(array $values, int $offset = null): int { - $a = (int) $offset; - foreach ($values as $value) { - if (is_array($value)) { - // recursively flatten any arrays, which may be provided for SET or IN() clauses - $a += $this->bindValues($value, $a); - } elseif (array_key_exists($a, $this->types)) { + protected function bindValues(array $values): bool { + // recursively flatten any arrays, which may be provided for SET or IN() clauses + $values = ValueInfo::flatten($values); + foreach ($values as $a => $value) { + if (array_key_exists($a, $this->types)) { $value = $this->cast($value, $this->types[$a]); $this->bindValue($value, $this->types[$a] % self::T_NOT_NULL, ++$a); } else { throw new Exception("paramTypeMissing", $a+1); } } - // once the last value is bound, check that all parameters have been supplied values and bind null for any missing ones + // once all values are bound, check that all parameters have been supplied values and bind null for any missing ones // SQLite will happily substitute null for a missing value, but other engines (viz. PostgreSQL) produce an error - if (is_null($offset)) { - while ($a < sizeof($this->types)) { - $this->bindValue(null, $this->types[$a] % self::T_NOT_NULL, ++$a); - } + for ($a = sizeof($values); $a < sizeof($this->types); $a++) { + $this->bindValue(null, $this->types[$a] % self::T_NOT_NULL, $a + 1); } - return $a - $offset; + return true; } } diff --git a/lib/Misc/ValueInfo.php b/lib/Misc/ValueInfo.php index 752704d..1b3d260 100644 --- a/lib/Misc/ValueInfo.php +++ b/lib/Misc/ValueInfo.php @@ -397,6 +397,17 @@ class ValueInfo { } } + public static function flatten(array $arr): array { + $arr = array_values($arr); + for ($a = 0; $a < sizeof($arr); $a++) { + if (is_array($arr[$a])) { + array_splice($arr, $a, 1, $arr[$a]); + $a--; + } + } + return $arr; + } + public static function int($value): int { $out = 0; if (is_null($value)) { diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index 9bf12ba..83053c5 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -639,4 +639,10 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { $out->f = $msec; return $out; } + + public function testFlattenArray() { + $arr = [1, [2, 3, [4, 5]], 6, [[7, 8], 9, 10]]; + $exp = range(1,10); + $this->assertSame($exp, I::flatten($arr)); + } } From b6dd8ab20d86a57abb1af84f34a1de72315f39cf Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 18 Oct 2019 13:11:03 -0400 Subject: [PATCH 09/20] Improvements to and proper tests for query builder --- lib/Misc/Query.php | 46 +++---- tests/cases/Db/MySQL/TestDatabase.php | 1 - tests/cases/Db/MySQLPDO/TestDatabase.php | 1 - tests/cases/Db/PostgreSQL/TestDatabase.php | 1 - tests/cases/Db/PostgreSQLPDO/TestDatabase.php | 1 - tests/cases/Db/SQLite3/TestDatabase.php | 1 - tests/cases/Db/SQLite3PDO/TestDatabase.php | 1 - tests/cases/Misc/TestQuery.php | 115 ++++++++++++++++++ tests/phpunit.dist.xml | 1 + 9 files changed, 140 insertions(+), 28 deletions(-) create mode 100644 tests/cases/Misc/TestQuery.php diff --git a/lib/Misc/Query.php b/lib/Misc/Query.php index 55d2cac..95b5c2c 100644 --- a/lib/Misc/Query.php +++ b/lib/Misc/Query.php @@ -29,61 +29,63 @@ class Query { $this->setBody($body, $types, $values); } - public function setBody(string $body = "", $types = null, $values = null): bool { + public function setBody(string $body = "", $types = null, $values = null): self { $this->qBody = $body; if (!is_null($types)) { $this->tBody[] = $types; $this->vBody[] = $values; } - return true; + return $this; } - public function setCTE(string $tableSpec, string $body, $types = null, $values = null): bool { + public function setCTE(string $tableSpec, string $body, $types = null, $values = null): self { $this->qCTE[] = "$tableSpec as ($body)"; if (!is_null($types)) { $this->tCTE[] = $types; $this->vCTE[] = $values; } - return true; + return $this; } - public function setWhere(string $where, $types = null, $values = null): bool { + public function setWhere(string $where, $types = null, $values = null): self { $this->qWhere[] = $where; if (!is_null($types)) { $this->tWhere[] = $types; $this->vWhere[] = $values; } - return true; + return $this; } - public function setWhereNot(string $where, $types = null, $values = null): bool { + public function setWhereNot(string $where, $types = null, $values = null): self { $this->qWhereNot[] = $where; if (!is_null($types)) { $this->tWhereNot[] = $types; $this->vWhereNot[] = $values; } - return true; + return $this; } - public function setGroup(string ...$column): bool { + public function setGroup(string ...$column): self { foreach ($column as $col) { $this->group[] = $col; } - return true; + return $this; } - public function setOrder(string $order): bool { - $this->order[] = $order; - return true; + public function setOrder(string ...$order): self { + foreach ($order as $o) { + $this->order[] = $o; + } + return $this; } - public function setLimit(int $limit, int $offset = 0): bool { + public function setLimit(int $limit, int $offset = 0): self { $this->limit = $limit; $this->offset = $offset; - return true; + return $this; } - public function pushCTE(string $tableSpec): bool { + public function pushCTE(string $tableSpec): self { // this function takes the query body and converts it to a common table expression, putting it at the bottom of the existing CTE stack // all WHERE, ORDER BY, and LIMIT parts belong to the new CTE and are removed from the main query $this->setCTE($tableSpec, $this->buildQueryBody(), [$this->tBody, $this->tWhere, $this->tWhereNot], [$this->vBody, $this->vWhere, $this->vWhereNot]); @@ -98,7 +100,7 @@ class Query { $this->order = []; $this->group = []; $this->setLimit(0, 0); - return true; + return $this; } public function __toString(): string { @@ -117,11 +119,11 @@ class Query { } public function getTypes(): array { - return [$this->tCTE, $this->tBody, $this->tWhere, $this->tWhereNot]; + return ValueInfo::flatten([$this->tCTE, $this->tBody, $this->tWhere, $this->tWhereNot]); } public function getValues(): array { - return [$this->vCTE, $this->vBody, $this->vWhere, $this->vWhereNot]; + return ValueInfo::flatten([$this->vCTE, $this->vBody, $this->vWhere, $this->vWhereNot]); } protected function buildQueryBody(): string { @@ -144,9 +146,9 @@ class Query { if (sizeof($this->order)) { $out .= " ORDER BY ".implode(", ", $this->order); } - // add LIMIT and OFFSET if the former is specified - if ($this->limit > 0) { - $out .= " LIMIT ".$this->limit; + // add LIMIT and OFFSET if either is specified + if ($this->limit > 0 || $this->offset > 0) { + $out .= " LIMIT ".($this->limit < 1 ? -1 : $this->limit); if ($this->offset > 0) { $out .= " OFFSET ".$this->offset; } diff --git a/tests/cases/Db/MySQL/TestDatabase.php b/tests/cases/Db/MySQL/TestDatabase.php index 4364170..9ad47ed 100644 --- a/tests/cases/Db/MySQL/TestDatabase.php +++ b/tests/cases/Db/MySQL/TestDatabase.php @@ -10,7 +10,6 @@ namespace JKingWeb\Arsse\TestCase\Db\MySQL; * @group slow * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\MySQL; diff --git a/tests/cases/Db/MySQLPDO/TestDatabase.php b/tests/cases/Db/MySQLPDO/TestDatabase.php index 6a7550e..e734555 100644 --- a/tests/cases/Db/MySQLPDO/TestDatabase.php +++ b/tests/cases/Db/MySQLPDO/TestDatabase.php @@ -11,7 +11,6 @@ namespace JKingWeb\Arsse\TestCase\Db\MySQLPDO; * @group optional * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\MySQLPDO; diff --git a/tests/cases/Db/PostgreSQL/TestDatabase.php b/tests/cases/Db/PostgreSQL/TestDatabase.php index 9fda4d9..e72c2a2 100644 --- a/tests/cases/Db/PostgreSQL/TestDatabase.php +++ b/tests/cases/Db/PostgreSQL/TestDatabase.php @@ -10,7 +10,6 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQL; * @group slow * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\PostgreSQL; diff --git a/tests/cases/Db/PostgreSQLPDO/TestDatabase.php b/tests/cases/Db/PostgreSQLPDO/TestDatabase.php index 6f8ef2a..22afa5d 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestDatabase.php +++ b/tests/cases/Db/PostgreSQLPDO/TestDatabase.php @@ -11,7 +11,6 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQLPDO; * @group optional * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\PostgreSQLPDO; diff --git a/tests/cases/Db/SQLite3/TestDatabase.php b/tests/cases/Db/SQLite3/TestDatabase.php index eab0970..ea30221 100644 --- a/tests/cases/Db/SQLite3/TestDatabase.php +++ b/tests/cases/Db/SQLite3/TestDatabase.php @@ -9,7 +9,6 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3; /** * @group optional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\SQLite3; diff --git a/tests/cases/Db/SQLite3PDO/TestDatabase.php b/tests/cases/Db/SQLite3PDO/TestDatabase.php index 079bcc1..751647a 100644 --- a/tests/cases/Db/SQLite3PDO/TestDatabase.php +++ b/tests/cases/Db/SQLite3PDO/TestDatabase.php @@ -8,7 +8,6 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3PDO; /** * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\SQLite3PDO; diff --git a/tests/cases/Misc/TestQuery.php b/tests/cases/Misc/TestQuery.php new file mode 100644 index 0000000..a1588f1 --- /dev/null +++ b/tests/cases/Misc/TestQuery.php @@ -0,0 +1,115 @@ +assertSame("select * from table where a = ?", $q->getQuery()); + $this->assertSame(["int"], $q->getTypes()); + $this->assertSame([3], $q->getValues()); + } + + public function testWhereQuery() { + // simple where clause + $q = (new Query("select * from table"))->setWhere("a = ?", "int", 3); + $this->assertSame("select * from table WHERE a = ?", $q->getQuery()); + $this->assertSame(["int"], $q->getTypes()); + $this->assertSame([3], $q->getValues()); + // compound where clause + $q = (new Query("select * from table"))->setWhere("a = ?", "int", 3)->setWhere("b = ?", "str", 4); + $this->assertSame("select * from table WHERE a = ? AND b = ?", $q->getQuery()); + $this->assertSame(["int", "str"], $q->getTypes()); + $this->assertSame([3, 4], $q->getValues()); + // negative where clause + $q = (new Query("select * from table"))->setWhereNot("a = ?", "int", 3); + $this->assertSame("select * from table WHERE NOT (a = ?)", $q->getQuery()); + $this->assertSame(["int"], $q->getTypes()); + $this->assertSame([3], $q->getValues()); + // compound negative where clause + $q = (new Query("select * from table"))->setWhereNot("a = ?", "int", 3)->setWhereNot("b = ?", "str", 4); + $this->assertSame("select * from table WHERE NOT (a = ? OR b = ?)", $q->getQuery()); + $this->assertSame(["int", "str"], $q->getTypes()); + $this->assertSame([3, 4], $q->getValues()); + // mixed where clause + $q = (new Query("select * from table"))->setWhereNot("a = ?", "int", 1)->setWhere("b = ?", "str", 2)->setWhereNot("c = ?", "int", 3)->setWhere("d = ?", "str", 4); + $this->assertSame("select * from table WHERE b = ? AND d = ? AND NOT (a = ? OR c = ?)", $q->getQuery()); + $this->assertSame(["str", "str", "int", "int"], $q->getTypes()); + $this->assertSame([2, 4, 1, 3], $q->getValues()); + } + + public function testGroupedQuery() { + $q = (new Query("select col1, col2, count(*) as count from table"))->setGroup("col1", "col2"); + $this->assertSame("select col1, col2, count(*) as count from table GROUP BY col1, col2", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + } + + public function testOrderedQuery() { + $q = (new Query("select col1, col2, col3 from table"))->setOrder("col1 desc", "col2")->setOrder("col3 asc"); + $this->assertSame("select col1, col2, col3 from table ORDER BY col1 desc, col2, col3 asc", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + } + + public function testLimitedQuery() { + // no offset + $q = (new Query("select * from table"))->setLimit(5); + $this->assertSame("select * from table LIMIT 5", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + // with offset + $q = (new Query("select * from table"))->setLimit(5, 10); + $this->assertSame("select * from table LIMIT 5 OFFSET 10", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + // no limit with offset + $q = (new Query("select * from table"))->setLimit(0, 10); + $this->assertSame("select * from table LIMIT -1 OFFSET 10", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + } + + public function testQueryWithCommonTableExpression() { + $q = (new Query("select * from table where a in (select * from cte where a = ?)", "int", 1))->setCTE("cte", "select * from other_table where a = ? and b = ?", ["str", "str"], [2, 3]); + $this->assertSame("WITH RECURSIVE cte as (select * from other_table where a = ? and b = ?) select * from table where a in (select * from cte where a = ?)", $q->getQuery()); + $this->assertSame(["str", "str", "int"], $q->getTypes()); + $this->assertSame([2, 3, 1], $q->getValues()); + // multiple CTEs + $q = (new Query("select * from table where a in (select * from cte1 join cte2 using (a) where a = ?)", "int", 1))->setCTE("cte1", "select * from other_table where a = ? and b = ?", ["str", "str"], [2, 3])->setCTE("cte2", "select * from other_table where c between ? and ?", ["datetime", "datetime"], [4, 5]); + $this->assertSame("WITH RECURSIVE cte1 as (select * from other_table where a = ? and b = ?), cte2 as (select * from other_table where c between ? and ?) select * from table where a in (select * from cte1 join cte2 using (a) where a = ?)", $q->getQuery()); + $this->assertSame(["str", "str", "datetime", "datetime", "int"], $q->getTypes()); + $this->assertSame([2, 3, 4, 5, 1], $q->getValues()); + } + + public function testQueryWithPushedCommonTableExpression() { + $q = (new Query("select * from table1"))->setWhere("a between ? and ?", ["datetime", "datetime"], [1, 2]) + ->setCTE("cte1", "select * from table2 where a = ? and b = ?", ["str", "str"], [3, 4]) + ->pushCTE("cte2") + ->setBody("select * from table3 join cte1 using (a) join cte2 using (a) where a = ?", "int", 5); + $this->assertSame("WITH RECURSIVE cte1 as (select * from table2 where a = ? and b = ?), cte2 as (select * from table1 WHERE a between ? and ?) select * from table3 join cte1 using (a) join cte2 using (a) where a = ?", $q->getQuery()); + $this->assertSame(["str", "str", "datetime", "datetime", "int"], $q->getTypes()); + $this->assertSame([3, 4, 1, 2, 5], $q->getValues()); + } + + public function testComplexQuery() { + $q = (new query("select *, ? as const from table", "datetime", 1)) + ->setWhereNot("b = ?", "bool", 2) + ->setGroup("col1", "col2") + ->setWhere("a = ?", "str", 3) + ->setLimit(4, 5) + ->setOrder("col3") + ->setCTE("cte", "select ? as const", "int", 6); + $this->assertSame("WITH RECURSIVE cte as (select ? as const) select *, ? as const from table WHERE a = ? AND NOT (b = ?) GROUP BY col1, col2 ORDER BY col3 LIMIT 4 OFFSET 5", $q->getQuery()); + $this->assertSame(["int", "datetime", "str", "bool"], $q->getTypes()); + $this->assertSame([6, 1, 3, 2], $q->getValues()); + } +} diff --git a/tests/phpunit.dist.xml b/tests/phpunit.dist.xml index 5489f94..e24e0d0 100644 --- a/tests/phpunit.dist.xml +++ b/tests/phpunit.dist.xml @@ -45,6 +45,7 @@ cases/Misc/TestValueInfo.php cases/Misc/TestDate.php + cases/Misc/TestQuery.php cases/Misc/TestContext.php cases/Misc/TestURL.php From 3ef1177f063489024be8563ab7ffca3e02f026f0 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 18 Oct 2019 13:20:28 -0400 Subject: [PATCH 10/20] Remove driver lists --- lib/Database.php | 15 --------------- lib/Service.php | 12 ------------ lib/User.php | 12 ------------ tests/cases/Database/SeriesMiscellany.php | 7 ------- tests/cases/User/TestUser.php | 7 ------- 5 files changed, 53 deletions(-) diff --git a/lib/Database.php b/lib/Database.php index b50f040..4036f91 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -78,21 +78,6 @@ class Database { return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function']; } - /** Lists the available database drivers, as an associative array with - * fully-qualified class names as keys, and human-readable descriptions as values - */ - public static function driverList(): array { - $sep = \DIRECTORY_SEPARATOR; - $path = __DIR__.$sep."Db".$sep; - $classes = []; - foreach (glob($path."*".$sep."Driver.php") as $file) { - $name = basename(dirname($file)); - $class = NS_BASE."Db\\$name\\Driver"; - $classes[$class] = $class::driverName(); - } - return $classes; - } - /** Returns the current (actual) schema version of the database; compared against self::SCHEMA_VERSION to know when an upgrade is required */ public function driverSchemaVersion(): int { return $this->db->schemaVersion(); diff --git a/lib/Service.php b/lib/Service.php index 93d4e9b..aed35c7 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -20,18 +20,6 @@ class Service { /** @var \DateInterval */ protected $interval; - public static function driverList(): array { - $sep = \DIRECTORY_SEPARATOR; - $path = __DIR__.$sep."Service".$sep; - $classes = []; - foreach (glob($path."*".$sep."Driver.php") as $file) { - $name = basename(dirname($file)); - $class = NS_BASE."User\\$name\\Driver"; - $classes[$class] = $class::driverName(); - } - return $classes; - } - public function __construct() { $driver = Arsse::$conf->serviceDriver; $this->drv = new $driver(); diff --git a/lib/User.php b/lib/User.php index 691d6fa..713f17c 100644 --- a/lib/User.php +++ b/lib/User.php @@ -20,18 +20,6 @@ class User { */ protected $u; - public static function driverList(): array { - $sep = \DIRECTORY_SEPARATOR; - $path = __DIR__.$sep."User".$sep; - $classes = []; - foreach (glob($path."*".$sep."Driver.php") as $file) { - $name = basename(dirname($file)); - $class = NS_BASE."User\\$name\\Driver"; - $classes[$class] = $class::driverName(); - } - return $classes; - } - public function __construct(\JKingWeb\Arsse\User\Driver $driver = null) { $this->u = $driver ?? new Arsse::$conf->userDriver; } diff --git a/tests/cases/Database/SeriesMiscellany.php b/tests/cases/Database/SeriesMiscellany.php index a7591bb..e91b83b 100644 --- a/tests/cases/Database/SeriesMiscellany.php +++ b/tests/cases/Database/SeriesMiscellany.php @@ -19,13 +19,6 @@ trait SeriesMiscellany { protected function tearDownSeriesMiscellany() { } - public function testListDrivers() { - $exp = [ - 'JKingWeb\\Arsse\\Db\\SQLite3\\Driver' => Arsse::$lang->msg("Driver.Db.SQLite3.Name"), - ]; - $this->assertArraySubset($exp, Database::driverList()); - } - public function testInitializeDatabase() { static::dbRaze(static::$drv); $d = new Database(true); diff --git a/tests/cases/User/TestUser.php b/tests/cases/User/TestUser.php index 1398b17..49fc472 100644 --- a/tests/cases/User/TestUser.php +++ b/tests/cases/User/TestUser.php @@ -24,13 +24,6 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { $this->drv = \Phake::mock(Driver::class); } - public function testListDrivers() { - $exp = [ - 'JKingWeb\\Arsse\\User\\Internal\\Driver' => Arsse::$lang->msg("Driver.User.Internal.Name"), - ]; - $this->assertArraySubset($exp, User::driverList()); - } - public function testConstruct() { $this->assertInstanceOf(User::class, new User($this->drv)); $this->assertInstanceOf(User::class, new User); From 7ac4fb47150fbdb5bb3e084cfaae7d743b02fc24 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 18 Oct 2019 16:09:01 -0400 Subject: [PATCH 11/20] Clarify PDO workaround for SQLite --- lib/Db/SQLite3/AbstractPDODriver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Db/SQLite3/AbstractPDODriver.php b/lib/Db/SQLite3/AbstractPDODriver.php index a743a25..bc7ea61 100644 --- a/lib/Db/SQLite3/AbstractPDODriver.php +++ b/lib/Db/SQLite3/AbstractPDODriver.php @@ -7,5 +7,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db\SQLite3; abstract class AbstractPDODriver extends Driver { + // this class exists solely so SQLite's PDO driver can call methods of the generic PDO driver via parent::method() + // if there's a better way to do this, please FIXME ;) use \JKingWeb\Arsse\Db\PDODriver; } From bad86cedb38c35dea6b7b744da127795d6f7a14a Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sat, 19 Oct 2019 12:13:42 -0400 Subject: [PATCH 12/20] Tests for bootstrapper --- tests/cases/TestArsse.php | 47 +++++++++++++++++++++++++++++++++++++++ tests/phpunit.dist.xml | 1 + 2 files changed, 48 insertions(+) create mode 100644 tests/cases/TestArsse.php diff --git a/tests/cases/TestArsse.php b/tests/cases/TestArsse.php new file mode 100644 index 0000000..179f399 --- /dev/null +++ b/tests/cases/TestArsse.php @@ -0,0 +1,47 @@ +import(['lang' => "test"]); + Arsse::load($conf2); + $this->assertSame($conf2, Arsse::$conf); + $this->assertSame($lang, Arsse::$lang); + $this->assertSame($db, Arsse::$db); + $this->assertSame($user, Arsse::$user); + \Phake::verify($lang)->set("test"); + } + + public function testLoadNewData() { + $conf = (new Conf)->import(['dbSQLite3File' => ":memory:"]); + Arsse::load($conf); + $this->assertInstanceOf(Conf::class, Arsse::$conf); + $this->assertInstanceOf(Lang::class, Arsse::$lang); + $this->assertInstanceOf(Database::class, Arsse::$db); + $this->assertInstanceOf(User::class, Arsse::$user); + } +} diff --git a/tests/phpunit.dist.xml b/tests/phpunit.dist.xml index e24e0d0..dd2ba50 100644 --- a/tests/phpunit.dist.xml +++ b/tests/phpunit.dist.xml @@ -129,6 +129,7 @@ cases/Service/TestService.php cases/CLI/TestCLI.php + cases/TestArsse.php cases/ImportExport/TestFile.php From 728eecfbb5696a94c4b463e71a331299c9add175 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sat, 19 Oct 2019 12:14:13 -0400 Subject: [PATCH 13/20] Additional service tests --- lib/Conf.php | 3 +++ lib/REST/Fever/API.php | 2 +- lib/Service.php | 2 ++ tests/cases/Service/TestService.php | 20 ++++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/Conf.php b/lib/Conf.php index 15a8345..13635c8 100644 --- a/lib/Conf.php +++ b/lib/Conf.php @@ -264,6 +264,7 @@ class Conf { $type |= Value::M_NULL; } } else { + // catch-all for custom properties $type = Value::T_MIXED; // @codeCoverageIgnore } $out[$p->name] = ['name' => $match[0], 'const' => $type]; @@ -286,6 +287,7 @@ class Conf { } switch (self::EXPECTED_TYPES[$key] ?? gettype($this->$key)) { case "integer": + // no properties are currently typed as integers return Value::normalize($value, Value::T_INT | $mode); // @codeCoverageIgnore case "double": return Value::normalize($value, Value::T_FLOAT | $mode); @@ -293,6 +295,7 @@ class Conf { case "object": return $value; default: + // this should never occur throw new Conf\Exception("ambiguousDefault", ['param' => $key]); // @codeCoverageIgnore } } diff --git a/lib/REST/Fever/API.php b/lib/REST/Fever/API.php index ac85aa8..16bd889 100644 --- a/lib/REST/Fever/API.php +++ b/lib/REST/Fever/API.php @@ -207,7 +207,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // indexed arrays $p->appendChild($this->makeXMLIndexed($v, $d->createElement($k), substr($k, 0, strlen($k) - 1))); } else { - // this case does not actually occur in a proper Fever response + // this case is never encountered with Fever's output $p->appendChild($this->makeXMLAssoc($v, $d->createElement($k))); // @codeCoverageIgnore } } diff --git a/lib/Service.php b/lib/Service.php index aed35c7..bd02fc9 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -40,11 +40,13 @@ class Service { } static::cleanupPost(); $t->add($this->interval); + // @codeCoverageIgnoreStart if ($loop) { do { @time_sleep_until($t->getTimestamp()); } while ($t->getTimestamp() > time()); } + // @codeCoverageIgnoreEnd } while ($loop); return $t; } diff --git a/tests/cases/Service/TestService.php b/tests/cases/Service/TestService.php index 3f6ea6b..a1db862 100644 --- a/tests/cases/Service/TestService.php +++ b/tests/cases/Service/TestService.php @@ -39,4 +39,24 @@ class TestService extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertTrue(Service::hasCheckedIn()); $this->assertFalse(Service::hasCheckedIn()); } + + public function testPerformPreCleanup() { + $this->assertTrue(Service::cleanupPre()); + \Phake::verify(Arsse::$db)->feedCleanup(); + \Phake::verify(Arsse::$db)->sessionCleanup(); + } + + public function testPerformShortPostCleanup() { + \Phake::when(Arsse::$db)->articleCleanup()->thenReturn(0); + $this->assertTrue(Service::cleanupPost()); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db, \Phake::times(0))->driverMaintenance(); + } + + public function testPerformFullPostCleanup() { + \Phake::when(Arsse::$db)->articleCleanup()->thenReturn(1); + $this->assertTrue(Service::cleanupPost()); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db)->driverMaintenance(); + } } From 71c7cd8fb17f2eb114ad6490a2a15dc403835f40 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sat, 19 Oct 2019 18:51:01 -0400 Subject: [PATCH 14/20] Full coverage! Fixes #66 --- lib/Service.php | 8 ++--- lib/Service/Driver.php | 2 +- lib/Service/Serial/Driver.php | 5 +-- lib/Service/Subprocess/Driver.php | 12 +++++-- tests/cases/Service/TestSerial.php | 47 +++++++++++++++++++++++++ tests/cases/Service/TestService.php | 21 +++++++++++ tests/cases/Service/TestSubprocess.php | 48 ++++++++++++++++++++++++++ tests/cases/TestArsse.php | 3 ++ tests/lib/Service.php | 13 +++++++ tests/phpunit.dist.xml | 2 ++ 10 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 tests/cases/Service/TestSerial.php create mode 100644 tests/cases/Service/TestSubprocess.php create mode 100644 tests/lib/Service.php diff --git a/lib/Service.php b/lib/Service.php index bd02fc9..ed234d6 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -12,18 +12,14 @@ class Service { const DRIVER_NAMES = [ 'serial' => \JKingWeb\Arsse\Service\Serial\Driver::class, 'subprocess' => \JKingWeb\Arsse\Service\Subprocess\Driver::class, - 'curl' => \JKingWeb\Arsse\Service\Curl\Driver::class, ]; /** @var Service\Driver */ protected $drv; - /** @var \DateInterval */ - protected $interval; public function __construct() { $driver = Arsse::$conf->serviceDriver; $this->drv = new $driver(); - $this->interval = Arsse::$conf->serviceFrequency; } public function watch(bool $loop = true): \DateTimeInterface { @@ -34,12 +30,12 @@ class Service { $list = Arsse::$db->feedListStale(); if ($list) { $this->drv->queue(...$list); + unset($list); $this->drv->exec(); $this->drv->clean(); - unset($list); } static::cleanupPost(); - $t->add($this->interval); + $t->add(Arsse::$conf->serviceFrequency); // @codeCoverageIgnoreStart if ($loop) { do { diff --git a/lib/Service/Driver.php b/lib/Service/Driver.php index 0f63383..e2dcf92 100644 --- a/lib/Service/Driver.php +++ b/lib/Service/Driver.php @@ -11,5 +11,5 @@ interface Driver { public static function requirementsMet(): bool; public function queue(int ...$feeds): int; public function exec(): int; - public function clean(): bool; + public function clean(): int; } diff --git a/lib/Service/Serial/Driver.php b/lib/Service/Serial/Driver.php index df3580c..dc2c74f 100644 --- a/lib/Service/Serial/Driver.php +++ b/lib/Service/Serial/Driver.php @@ -36,8 +36,9 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - public function clean(): bool { + public function clean(): int { + $out = sizeof($this->queue); $this->queue = []; - return true; + return $out; } } diff --git a/lib/Service/Subprocess/Driver.php b/lib/Service/Subprocess/Driver.php index 5e79ed0..0986f2c 100644 --- a/lib/Service/Subprocess/Driver.php +++ b/lib/Service/Subprocess/Driver.php @@ -33,7 +33,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { $id = (int) array_shift($this->queue); $php = escapeshellarg(\PHP_BINARY); $arsse = escapeshellarg($_SERVER['argv'][0]); - array_push($pp, popen("$php $arsse feed refresh $id", "r")); + array_push($pp, $this->execCmd("$php $arsse feed refresh $id")); } while ($pp) { $p = array_pop($pp); @@ -43,8 +43,14 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - public function clean(): bool { + /** @codeCoverageIgnore */ + protected function execCmd(string $cmd) { + return popen($cmd, "r"); + } + + public function clean(): int { + $out = sizeof($this->queue); $this->queue = []; - return true; + return $out; } } diff --git a/tests/cases/Service/TestSerial.php b/tests/cases/Service/TestSerial.php new file mode 100644 index 0000000..5a96078 --- /dev/null +++ b/tests/cases/Service/TestSerial.php @@ -0,0 +1,47 @@ +assertTrue(Driver::requirementsMet()); + $this->assertInstanceOf(DriverInterface::class, new Driver); + } + + public function testFetchDriverName() { + $this->assertTrue(strlen(Driver::driverName()) > 0); + } + + public function testEnqueueFeeds() { + $d = new Driver; + $this->assertSame(3, $d->queue(1, 2, 3)); + $this->assertSame(5, $d->queue(4, 5)); + $this->assertSame(5, $d->clean()); + $this->assertSame(1, $d->queue(5)); + } + + public function testRefreshFeeds() { + $d = new Driver; + $d->queue(1, 4, 3); + $this->assertSame(Arsse::$conf->serviceQueueWidth, $d->exec()); + \Phake::verify(Arsse::$db)->feedUpdate(1); + \Phake::verify(Arsse::$db)->feedUpdate(4); + \Phake::verify(Arsse::$db)->feedUpdate(3); + } +} diff --git a/tests/cases/Service/TestService.php b/tests/cases/Service/TestService.php index a1db862..102a9ce 100644 --- a/tests/cases/Service/TestService.php +++ b/tests/cases/Service/TestService.php @@ -59,4 +59,25 @@ class TestService extends \JKingWeb\Arsse\Test\AbstractTest { \Phake::verify(Arsse::$db)->articleCleanup(); \Phake::verify(Arsse::$db)->driverMaintenance(); } + + public function testRefreshFeeds() { + // set up mock database actions + \Phake::when(Arsse::$db)->metaSet->thenReturn(true); + \Phake::when(Arsse::$db)->feedCleanup->thenReturn(true); + \Phake::when(Arsse::$db)->sessionCleanup->thenReturn(true); + \Phake::when(Arsse::$db)->articleCleanup->thenReturn(0); + \Phake::when(Arsse::$db)->feedListStale->thenReturn([1,2,3]); + // perform the test + $d = \Phake::mock(\JKingWeb\Arsse\Service\Driver::class); + $s = new \JKingWeb\Arsse\Test\Service($d); + $this->assertInstanceOf(\DateTimeInterface::class, $s->watch(false)); + // verify invocations + \Phake::verify($d)->queue(1, 2, 3); + \Phake::verify($d)->exec(); + \Phake::verify($d)->clean(); + \Phake::verify(Arsse::$db)->feedCleanup(); + \Phake::verify(Arsse::$db)->sessionCleanup(); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db)->metaSet("service_last_checkin", $this->anything(), "datetime"); + } } diff --git a/tests/cases/Service/TestSubprocess.php b/tests/cases/Service/TestSubprocess.php new file mode 100644 index 0000000..c02c4b2 --- /dev/null +++ b/tests/cases/Service/TestSubprocess.php @@ -0,0 +1,48 @@ +assertTrue(Driver::requirementsMet()); + $this->assertInstanceOf(DriverInterface::class, new Driver); + } + + public function testFetchDriverName() { + $this->assertTrue(strlen(Driver::driverName()) > 0); + } + + public function testEnqueueFeeds() { + $d = new Driver; + $this->assertSame(3, $d->queue(1, 2, 3)); + $this->assertSame(5, $d->queue(4, 5)); + $this->assertSame(5, $d->clean()); + $this->assertSame(1, $d->queue(5)); + } + + public function testRefreshFeeds() { + $d = \Phake::partialMock(Driver::class); + \Phake::when($d)->execCmd->thenReturnCallback(function(string $cmd) { + // FIXME: Does this work in Windows? + return popen("echo ".escapeshellarg($cmd), "r"); + }); + $this->assertSame(3, $d->queue(1, 4, 3)); + $this->assertSame(Arsse::$conf->serviceQueueWidth, $d->exec()); + \Phake::verify($d, \Phake::times(3))->execCmd; + } +} diff --git a/tests/cases/TestArsse.php b/tests/cases/TestArsse.php index 179f399..f28e7ee 100644 --- a/tests/cases/TestArsse.php +++ b/tests/cases/TestArsse.php @@ -37,6 +37,9 @@ class TestArsse extends \JKingWeb\Arsse\Test\AbstractTest { } public function testLoadNewData() { + if (!\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet() && !\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) { + $this->markTestSkipped("A functional SQLite interface is required for this test"); + } $conf = (new Conf)->import(['dbSQLite3File' => ":memory:"]); Arsse::load($conf); $this->assertInstanceOf(Conf::class, Arsse::$conf); diff --git a/tests/lib/Service.php b/tests/lib/Service.php new file mode 100644 index 0000000..cfd11f4 --- /dev/null +++ b/tests/lib/Service.php @@ -0,0 +1,13 @@ +drv = $drv; + } +} diff --git a/tests/phpunit.dist.xml b/tests/phpunit.dist.xml index dd2ba50..997c6a7 100644 --- a/tests/phpunit.dist.xml +++ b/tests/phpunit.dist.xml @@ -128,6 +128,8 @@ cases/Service/TestService.php + cases/Service/TestSerial.php + cases/Service/TestSubprocess.php cases/CLI/TestCLI.php cases/TestArsse.php From c59cdfef76771c50226210461efb7ea3db4c0c97 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Fri, 25 Oct 2019 15:16:35 -0400 Subject: [PATCH 15/20] Whitespace fixes --- lib/Db/AbstractStatement.php | 2 +- lib/Misc/URL.php | 2 +- tests/cases/Misc/TestValueInfo.php | 2 +- tests/lib/AbstractTest.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Db/AbstractStatement.php b/lib/Db/AbstractStatement.php index 8471986..45b6801 100644 --- a/lib/Db/AbstractStatement.php +++ b/lib/Db/AbstractStatement.php @@ -71,7 +71,7 @@ abstract class AbstractStatement implements Statement { } protected function bindValues(array $values): bool { - // recursively flatten any arrays, which may be provided for SET or IN() clauses + // recursively flatten any arrays, which may be provided for SET or IN() clauses $values = ValueInfo::flatten($values); foreach ($values as $a => $value) { if (array_key_exists($a, $this->types)) { diff --git a/lib/Misc/URL.php b/lib/Misc/URL.php index da49eff..4a4459c 100644 --- a/lib/Misc/URL.php +++ b/lib/Misc/URL.php @@ -145,7 +145,7 @@ class URL { } /** Appends data to a URL's query component - * + * * @param string $url The input URL * @param string $data The data to append. This should already be escaped where necessary and not start with any delimiter * @param string $glue The query subcomponent delimiter, usually "&". If the URL has no query, "?" will be prepended instead diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index 83053c5..2d5ffc4 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -642,7 +642,7 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { public function testFlattenArray() { $arr = [1, [2, 3, [4, 5]], 6, [[7, 8], 9, 10]]; - $exp = range(1,10); + $exp = range(1, 10); $this->assertSame($exp, I::flatten($arr)); } } diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index a2e66a3..f3a1ffb 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -74,7 +74,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { if (isset($params)) { if (is_array($params)) { $params = implode("&", array_map(function($v, $k) { - return rawurlencode($k).(isset($v) ? "=".rawurlencode($v) : ""); + return rawurlencode($k).(isset($v) ? "=".rawurlencode($v) : ""); }, $params, array_keys($params))); } $url = URL::queryAppend($url, (string) $params); @@ -90,7 +90,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { if (is_string($body) && in_array(strtolower($type), ["", "application/x-www-form-urlencoded"])) { parse_str($body, $parsedBody); } elseif (!is_string($body) && in_array(strtolower($type), ["application/json", "text/json"])) { - $body = json_encode($body, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); + $body = json_encode($body, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); } elseif (!is_string($body) && in_array(strtolower($type), ["", "application/x-www-form-urlencoded"])) { $parsedBody = $body; $body = http_build_query($body, "a", "&"); From 0e5b242c67e073b43a59f9acdce29a1285657922 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 28 Oct 2019 11:07:04 -0400 Subject: [PATCH 16/20] Version bump --- CHANGELOG | 2 +- lib/Arsse.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5448364..a381c82 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Version 0.8.1 (2019-??-??) +Version 0.8.1 (2019-10-28) ========================== Bug fixes: diff --git a/lib/Arsse.php b/lib/Arsse.php index 82c4332..6808831 100644 --- a/lib/Arsse.php +++ b/lib/Arsse.php @@ -7,7 +7,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse; class Arsse { - const VERSION = "0.8.0"; + const VERSION = "0.8.1"; /** @var Lang */ public static $lang; From 733f0d7fd5bbda710e669e711b7d768b4603db70 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 28 Oct 2019 12:43:47 -0400 Subject: [PATCH 17/20] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22e8e51..e6ed075 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Information on how to install and use the software can be found in [the manual]( # Installing from source -The main repository for The Arsse can be found at [code.mensbeam.com](https://code.mensbeam.com/MensBeam/arsse/), with a mirror also available [at GitHub](https://github.com/meansbeam/arsse/). The main repository is preferred, as the GitHub mirror can sometimes be out of date. +The main repository for The Arsse can be found at [code.mensbeam.com](https://code.mensbeam.com/MensBeam/arsse/), with a mirror also available [at GitHub](https://github.com/mensbeam/arsse/). The main repository is preferred, as the GitHub mirror can sometimes be out of date. [Composer](https://getcomposer.org/) is required to manage PHP dependencies. After cloning the repository or downloading a source code tarball, running `composer install` will download all the required dependencies, and will advise if any PHP extensions need to be installed. If not installing as a programming environment, running `composer install --no-dev` is recommended. From bbc96e4f372424a4b0b14c3b29fc845dd4a8a9e1 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 28 Oct 2019 13:09:10 -0400 Subject: [PATCH 18/20] Remove reference to obsolete CSS-only manual task --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index e6ed075..0a4f0af 100644 --- a/README.md +++ b/README.md @@ -105,8 +105,6 @@ The Arsse's user manual, made using [Daux](https://daux.io/), can be compiled by The manual employs a custom theme derived from the standard Daux theme. If the standard Daux theme receives improvements, the custom theme can be rebuilt by running `./robo manual:theme`. This requires that [NodeJS](https://nodejs.org) and [Yarn](https://yarnpkg.com/) be installed, but JavaScript tools are not required to modify The Arsse itself, nor the content of the manual. -The Robo task `manual:css` will recompile the theme's stylesheet without rebuilding the entire theme. - ## Packaging a release Producing a release package is done by running `./robo package`. This performs the following operations: From 5ede4cbdb25950188b5a38a0d8682c4d48b3ba9d Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 28 Oct 2019 13:14:31 -0400 Subject: [PATCH 19/20] Clarify coverage requirements --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a4f0af..0658d78 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ There is also a `test:quick` Robo task which excludes slower tests, and a `test: ### Test coverage -Computing the coverage of tests can be done by running `./robo coverage`. Either [phpdbg](https://php.net/manual/en/book.phpdbg.php) or [Xdebug](https://xdebug.org) is required for this. An HTML-format coverage report will be written to `/tests/coverage/`. +Computing the coverage of tests can be done by running `./robo coverage`, after which an HTML-format coverage report will be written to `/tests/coverage/`. Either [Xdebug](https://xdebug.org) or [phpdbg](https://php.net/manual/en/book.phpdbg.php) is required for this. Xdebug is generally recommended as it is better maintained, though phpdbg is significantly faster. If using Xdebug, the extension need not be enabled globally; PHPUnit will enable it when needed. ## Enforcing coding style From c6b79d49ba36ed0eabf586263a9e8613b6edbdfa Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 28 Oct 2019 19:48:10 -0400 Subject: [PATCH 20/20] Documentation corrections --- .../020_Getting_Started/040_Database_Setup/010_PostgreSQL.md | 2 +- docs/en/020_Getting_Started/040_Database_Setup/020_MySQL.md | 4 ++-- docs/en/020_Getting_Started/050_Configuration.md | 2 +- docs/en/020_Getting_Started/index.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md b/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md index 7dc1af2..5127242 100644 --- a/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md +++ b/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md @@ -22,7 +22,7 @@ sudo -u postgres psql -c "CREATE USER arsseuser WITH PASSWORD 'super secret pass sudo -u postgres psql -c "CREATE DATABASE arssedb WITH OWNER arsseuser" ``` -Tha Arsse must then be configured to use the created database. A suitable [configuration file](/en/Getting_Started/Configuration) might look like this: +The Arsse must then be configured to use the created database. A suitable [configuration file](/en/Getting_Started/Configuration) might look like this: ```php