.gitignore000066400000000000000000000006531516067327100130620ustar00rootroot00000000000000cache/ vendor/ build/ *.diff *.err *.orig *.log *.rej *.swo *.swp *.zip *.vi *~ *.sass-cache .DS_Store ._* Thumbs.db .cache node_modules /config.ini /git-test /git-test2 /bower_components .idea/workspace.xml .idea/tasks.xml .idea/profiles_settings.xml .idea/inspectionProfiles/Project_Default.xml .idea/inspectionProfiles/profiles_settings.xml node_modules/.yarn-integrity /public/webpack /public/generated /twig/layout.twig.idea/000077500000000000000000000000001516067327100120465ustar00rootroot00000000000000.idea/codeStyleSettings.xml000066400000000000000000000004251516067327100162450ustar00rootroot00000000000000 .idea/codeStyles/000077500000000000000000000000001516067327100141645ustar00rootroot00000000000000.idea/codeStyles/codeStyleConfig.xml000066400000000000000000000002251516067327100177660ustar00rootroot00000000000000 .idea/gitlist.iml000066400000000000000000000107301516067327100142310ustar00rootroot00000000000000 .idea/misc.xml000066400000000000000000000002561516067327100135260ustar00rootroot00000000000000 .idea/modules.xml000066400000000000000000000004121516067327100142350ustar00rootroot00000000000000 .idea/php.xml000066400000000000000000000070521516067327100133630ustar00rootroot00000000000000 .idea/vcs.xml000066400000000000000000000002471516067327100133660ustar00rootroot00000000000000 .npmrc000066400000000000000000000001051516067327100122020ustar00rootroot00000000000000https://registry.npmjs.org/= registry=https://registry.npmjs.org/ .scrutinizer.yml000077500000000000000000000010501516067327100142470ustar00rootroot00000000000000checks: php: true javascript: true filter: excluded_paths: - test/* - node_modules/* - build/* - artifacts/* build: cache: disabled: true environment: google_chrome: use_latest: true php: version: 7.2 dependencies: before: - export LATEST=$(nvm ls-remote | tail -1) - nvm install $LATEST # - nvm use $LATEST tests: override: - command: ./vendor/bin/phpunit -c phpunit.xml coverage: file: build/coverage.xml format: php-clover .travis.yml000077500000000000000000000017601516067327100132060ustar00rootroot00000000000000sudo: required dist: trusty language: php php: - '7.1' - '7.2' - nightly before_install: - composer config --global github-oauth.github.com $GITHUB_TOKEN before_script: composer install notifications: email: recipients: - alabard@gmail.com on_success: change on_failure: change env: global: secure: NPmPNUmMuxBj9xHcXLFUf3KxPUMlXgcuZeVM3IaV4/lCBd4GXQ5wVTKBb7N7v90EDijLvNXsIQ0sSDnVAkteTi+O0sJUcAG1DKJMKIDU2HYd2llM+hbo2Nhfpm/jTOuZg6VTqFLKK1wUVFXPtHyX6sbbJRDCstDdLIb10noDnk5iaTP2LtDKd2lMcCjsymP1d+sqCwwREwKj/TIGqoFdkUTKbxy2MgQrV8kT+WwXAhq5l2x7MaQMOO2zcN+qI3T9yYyLyuB0DYnxv+U1AByQQoSG37rEySy6orZNDuN9BOMNFak2knbO0RUWuLnR3/Vj4VLDZx617ONNJ29PUgXRuzeDg51KBMo6BMT+PKUJdBx6710hOx3clgr3CRHJ/HzTcU4JiY6LRvxUsegLd0J2oGU7KBrVBbswSi5xY/NIhDp8dpRlKbmslDrg4kJgd5bbuyNOWsM5irGyYIi8R2oYzNJBQAKAQEjyjI2T/m0u+g8gGAlTr4fjWRkCBgz0ufnJu1tdnXeJ5K6XxP+NqvpXMHv+kehL4ElWAm3CHSLyeQBruzX2qfL3Ik4vAI5/RWeqoJGcPaB2vxELulcexqLkegXg+tOnXedKEvrVaT1l5SejdbPyO57PKL3t/H8ru3dpInS4muqD3EcZ/2eZB1puPEE/+bJWmNMqHAYfOW2mMwc= Gruntfile.js000077500000000000000000000036551516067327100133770ustar00rootroot00000000000000 module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-less'); const builder = require(`corifeus-builder`); const loader = new builder.loader(grunt); loader.js({ replacer: { type: 'p3x', npmio: false, }, config: { clean: { generated: [ 'public/generated', 'public/webpack', ], css: [ 'public/generated/css' ] /* themes: [ themeDir ], fonts: [ 'public/fonts' ] */ }, copy: { tweomji: { files: [ { cwd: 'node_modules/twemoji/2/svg', expand: true, src: [ '**', ], dest: './public/generated/twemoji/svg' }, ] }, }, less: { development: require('./grunt/less').lessSettings(grunt), }, watch: { less: { files: ['public/less/*.*'], tasks: ['clean:css', 'less'], options: { atBegin: true, //spawn: false, }, }, } } }); grunt.registerTask('default', ['clean', 'less', 'copy', 'cory-npm', 'cory-replace']); grunt.registerTask('build', ['default']); }; INSTALL.md000066400000000000000000000076201516067327100125230ustar00rootroot00000000000000[//]: #@corifeus-header # 🤖 P3X Gitlist [//]: #@corifeus-header:end # GitList Installation * Download GitList from [https://github.com/patrikx3/gitlist/releases](https://github.com/patrikx3/gitlist/releases/) and decompress to your `/var/www/gitlist` folder, or anywhere else you want to place GitList. * Rename the `config.example.ini-example` file to `config.ini`. * Open up the `config.ini` and configure your installation. You'll have to provide where your repositories are located and the base GitList URL (in our case, http://localhost/gitlist). * Create the cache folder and give read/write permissions to your web server user: ``` cd /var/www/gitlist mkdir -p cache chmod 777 cache ``` That's it, installation complete! ## Webserver configuration Apache is the "default" webserver for GitList. You will find the configuration inside the `.htaccess` file. However, nginx and lighttpd are also supported. To make it to be more secure: All `PHP` files will be in the `root` and only `index.php`, `images`, `icons`, `svg`, `css`, `js`bundle files will be in the `public` subdir. ### nginx server.conf ``` server { server_name MYSERVER; access_log /var/log/nginx/MYSERVER.access.log combined; error_log /var/log/nginx/MYSERVER.error.log error; root /var/www/DIR/public; index index.php; # auth_basic "Restricted"; # auth_basic_user_file .htpasswd; location = /robots.txt { allow all; log_not_found off; access_log off; } location ~* ^/index.php.*$ { fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # if you're using php7.2-fpm via socket fastcgi_pass unix:/var/run/php7.2-fpm.sock; include snippets/fastcgi-php.conf;; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass $php_listener; } location ~ /\.ht { deny all; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { add_header Vary "Accept-Encoding"; expires max; try_files $uri @gitlist; tcp_nodelay off; tcp_nopush on; } # location ~* \.(git|svn|patch|htaccess|log|route|plist|inc|json|pl|po|sh|ini|sample|kdev4)$ { # deny all; # } } ``` ### lighthttpd I do not use `lighthttpd`, but you know what I mean. Make sure only, the `gitlist/public` folder should be enabled. ``` # GitList is located in /var/www/gitlist/ server.document-root = "/var/www" url.rewrite-once = ( "^/gitlist/web/.+" => "$0", "^/gitlist/favicon\.ico$" => "$0", "^/gitlist(/[^\?]*)(\?.*)?" => "/gitlist/index.php$1$2" ) ``` ### hiawatha I do not use `hiawatha`, but you know what I mean. Make sure only, the `gitlist/public` folder should be enabled. ``` UrlToolkit { ToolkitID = gitlist RequestURI isfile Return # If you have example.com/gitlist/ ; Otherwise remove "/gitlist" below Match ^/gitlist/.* Rewrite /gitlist/index.php Match ^/gitlist/.*\.ini DenyAccess } ``` [//]: #@corifeus-footer --- [**P3X-GITLIST**](https://pages.corifeus.com/gitlist) Build v2.7.5-743 [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) ## P3X Sponsors [IntelliJ - The most intelligent Java IDE](https://www.jetbrains.com) [![JetBrains](https://cdn.corifeus.com/assets/svg/jetbrains-logo.svg)](https://www.jetbrains.com/) [![NoSQLBooster](https://cdn.corifeus.com/assets/png/nosqlbooster-70x70.png)](https://www.nosqlbooster.com/) [The Smartest IDE for MongoDB](https://www.nosqlbooster.com) [//]: #@corifeus-footer:endLICENSE000066400000000000000000000051721516067327100121000ustar00rootroot00000000000000MIT License Copyright (c) 2018 Patrik Laszlo / patrikx3 / https://patrikx3.com and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ Copyright (c) 2012-2015, Klaus Silveira and contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of GitList nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. README.md000066400000000000000000000142551516067327100123540ustar00rootroot00000000000000[//]: #@corifeus-header [![Build Status](https://travis-ci.org/patrikx3/gitlist.svg?branch=master)](https://travis-ci.org/patrikx3/gitlist) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/patrikx3/gitlist/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/patrikx3/gitlist/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/patrikx3/gitlist/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/patrikx3/gitlist/?branch=master) # 🤖 P3X Gitlist v2.7.5-743 This is an open-source project. Star this repository if you like it, or even donate! Thank you so much! :) I run my own server with dynamic IP address so it may happen that the server can not be reachable for about max 15 minutes due to the dynamic DNS. The server may also be unreachable when I backup the SSD with Clonzilla (very rarely) or an electrical issue (but this should not happen again). When the server is down, please hang on for 15-30 minutes and the server will be back up. All my domains (patrikx3.com and corifeus.com) could have errors since I am developing in my free time. However, it is usually stable. ### Node Version Requirement ``` >=8.9.0 ``` ### Built on Node ``` v10.1.0 ``` The ```async``` and ```await``` keywords are required. Install NodeJs: https://nodejs.org/en/download/package-manager/ # Description [//]: #@corifeus-header:end This is Klaus Silveira's fork, with multiple themes (dark/light), sub-modules, uglify-es, webpack, toast, pure Bootstrap 3 and upgraded to PHP7.1 with all components. ### PHP > 7.1 only [README](artifacts/php-7.2-ubuntu.md) # Release version/update info ## Package Done, just put on your server, nothing to build: https://github.com/patrikx3/gitlist/releases ### Web server You might need to tune your web server, to only parse the `public/index.php` PHP script, so you can view your `php` files in `P3X GitList`. #### PHP Memory It is possible, that some big commits are huge and for now, it loads everything. In `V3`, everything will be `lazy`, but looks like I had a huge commit and I had to set my `PHP.ini` had to change like: ```text max_execution_time = 120 memory_limit = 512M ``` I checked and the big commit was using 258 MBytes. Though even the `browser` is almost `hanging`, take a long time to `render` the page. ## There is a changing break ### First Before, everything was in the `root` of the web server. Which is not secure. For now, you can create a folder eg. `/var/www/gitlist.me.com/` and make sure, that you server does not point to `/var/www/gitlist.me.com/`, but instead, point to `/var/www/gitlist.me.com/public`. ### Second The `config.ini` file with `url_subdir` or later `clone_subdir` variable has been changed to the `git_clone_subdir` variable. ### Third 😀 I removed `Babel`, we are in 2018. If you want use an older `Browser` (like iPhone 5), you can probably install latest `Chrome` and it will work. Besides, without `Babel` the `JavaScript` is much faster. (At work, without `Babel`, bigger `JS` file and works `20x` faster.) #### The last version with Babel https://github.com/patrikx3/gitlist/releases/tag/2.0.4-579 The following versions are not using `Babel`!!!! Yikes! ### The next release **P3X GitList v3.0 will migrate from `Silex` to `Symphony` on the server side and the frontend will be using `Bootstrap 4` with `AngularJS`. That version will expect to work with `async/await` and the latest `JavaScript` versions, as now, no `Babel` anymore!!!** ### Unreleased / in progress I think this `v2.6` is complete. * Allow to edit non binary files * Upload binary files * Add new files * Delete files * Localization * In submodules, if the "submodule" and "path" is not the same, it chokes (it should work the submodule name and path are not the same) * Works * submodule "path/name" * path path/name * Not working * submodule "name" * path path/name [Change log](changelog.md) ... # Old info https://github.com/klaussilveira/gitlist # Live demo http://gitlist.patrikx3.com/ # Installation ## Requirements By now `composer` is not enough. We are using `webpack`, `babel`, `less`, `grunt` ... For the build on your workstation (less, babel, Bootstrap themes, and webpack): * ```NodeJs``` >= 10 * ```Grunt``` (npm install -g npm grunt-cli) * `Composer` In order to run GitList on your server, you'll need: * ```git``` * ```Apache``` with ```mod_rewrite``` enabled or ```nginx``` * ```PHP``` >= 7.1 ## By hand If you have Composer in your path, things get easier. But you know the drill. If want to get the project dependencies, and build everything: ``` git clone https://github.com/patrikx3/gitlist.git curl -s http://getcomposer.org/installer | php php composer.phar install # i use Node v10 and NPM v6 sudo npm install -g npm grunt-cli npm install # if you do not want to create a release # just work on it # now the js and css is built on the fly # in the ./public folder npm run watch # if you have bash and want to create a full release # and strip all unneeded files, # optimize the packagist vendor folder # you might need zip from linux # the files will be in the ./build/release folder # and the zip is in the ./build/release/p3x-gitlist-a.b.c.zip file ./scripts/release.sh ``` [Install](INSTALL.md) - here. [//]: #@corifeus-footer --- [**P3X-GITLIST**](https://pages.corifeus.com/gitlist) Build v2.7.5-743 [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) ## P3X Sponsors [IntelliJ - The most intelligent Java IDE](https://www.jetbrains.com) [![JetBrains](https://cdn.corifeus.com/assets/svg/jetbrains-logo.svg)](https://www.jetbrains.com/) [![NoSQLBooster](https://cdn.corifeus.com/assets/png/nosqlbooster-70x70.png)](https://www.nosqlbooster.com/) [The Smartest IDE for MongoDB](https://www.nosqlbooster.com) [//]: #@corifeus-footer:endartifacts/000077500000000000000000000000001516067327100130465ustar00rootroot00000000000000artifacts/config.ini000066400000000000000000000032451516067327100150200ustar00rootroot00000000000000[git] client = '/usr/bin/git' ; Your git executable path default_branch = 'master' ; Default branch when HEAD is detached repositories[] = '../git-test' ; Path to your repositories ; If you wish to add more repositories, just add a new line ; WINDOWS USERS ;client = '"C:\Program Files (x86)\Git\bin\git.exe"' ; Your git executable path ;repositories[] = 'C:\Path\to\Repos\' ; Path to your repositories ; You can hide repositories from GitList, just copy this for each repository you want to hide ; hidden[] = '/home/git/repositories/BetaTest' [app] debug = false cache = false title = "" ; big files can block the browser in code mirror, so there is a limit codemirror_full_limit = 48 [clone_button] ; ssh remote show_ssh_remote = true ; display remote URL for SSH ssh_user = 'git' ; user to use for cloning via SSH ; http remote show_http_remote = true ; display remote URL for HTTP use_https = true ; generate URL with https:// ; if cloning via GIT ; we cannot find out the subdir ; so we have to add this git clone subdir ; eg git_clone_subdir = 'subdir/' git_clone_subdir = '' ; has to end with trailing slash http_user = '' ; user to use for cloning via HTTP (default: none) http_user_dynamic = false ; when enabled, http_user is set to $_SERVER['PHP_AUTH_USER'] ; If you need to specify custom filetypes for certain extensions, do this here [filetypes] ; extension = type ; dist = xml ; If you need to set file types as binary or not, do this here [binary_filetypes] ; extension = true ; svh = false ; map = true ; set the timezone [date] timezone = Europe/Budapest format = 'Y.m.d. H:i:s' ; custom avatar service [avatar] ; url = '//gravatar.com/avatar/' ; query[] = 'd=identicon'artifacts/php-7.2-ubuntu.md000066400000000000000000000022621516067327100160050ustar00rootroot00000000000000[//]: #@corifeus-header # 🤖 P3X Gitlist [//]: #@corifeus-header:end # Install PHP 7.2 on Ubuntu before Bionic ```bash sudo add-apt-repository ppa:ondrej/php # enter (empty) sudo apt update sudo apt install -y php7.2 sudo apt upgrade -y ``` [//]: #@corifeus-footer --- [**P3X-GITLIST**](https://pages.corifeus.com/gitlist) Build v2.7.5-743 [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) ## P3X Sponsors [IntelliJ - The most intelligent Java IDE](https://www.jetbrains.com) [![JetBrains](https://cdn.corifeus.com/assets/svg/jetbrains-logo.svg)](https://www.jetbrains.com/) [![NoSQLBooster](https://cdn.corifeus.com/assets/png/nosqlbooster-70x70.png)](https://www.nosqlbooster.com/) [The Smartest IDE for MongoDB](https://www.nosqlbooster.com) [//]: #@corifeus-footer:endboot.php000066400000000000000000000010541516067327100125420ustar00rootroot00000000000000mount('', new GitList\Controller\MainController()); $app->mount('', new GitList\Controller\BlobController()); $app->mount('', new GitList\Controller\CommitController()); $app->mount('', new GitList\Controller\TreeController()); $app->mount('', new GitList\Controller\NetworkController()); $app->mount('', new GitList\Controller\TreeGraphController()); $app->mount('', new GitList\Controller\GitController()); return $app; changelog.md000066400000000000000000000112661516067327100133450ustar00rootroot00000000000000[//]: #@corifeus-header # 🤖 P3X Gitlist [//]: #@corifeus-header:end ### v2.6.0 * network and graph works with Bootstrap 3 totally ### v2.5.0 * you can edit files now ### v2.0.12-585 * removed `Babel` 😀 ### v2.0.4-579 * Automated build with webpack and grunt ### v1.1.18-573 * for big commits and changing the theme, it calculated the time it was loading the full commit list and it is about the same time when you change the theme, it added an overlay and this text eg. `9 seconds to switch the theme` * automatic versions generated with grunt ### v1.1.14 * added overlay when loading big commits ### v1.1.12 * allow CodeMirror show toggle height 300px vs all ### v1.1.11 * Make to use the tag/branch button like GitHub ### v1.1.10 * total dark/light mode (CodeMirror, diff, Markdown) ### v1.1.9 * markdown dark mode * we automatically load the next commit, when we are on the bottom of the page * minor toast fix ### v1.1.8 The `config.ini` file with `url_subdir` or later `clone_subdir` variable has been changed to the `git_clone_subdir` variable. ### v1.1.7 The following `CodeMirror` syntax highlighting has been added: ```js require('codemirror/mode/cmake/cmake'); require('codemirror/mode/css/css'); require('codemirror/mode/dockerfile/dockerfile'); require('codemirror/mode/go/go'); require('codemirror/mode/handlebars/handlebars'); require('codemirror/mode/htmlmixed/htmlmixed'); require('codemirror/mode/javascript/javascript'); require('codemirror/mode/jsx/jsx'); require('codemirror/mode/perl/perl'); require('codemirror/mode/php/php'); require('codemirror/mode/powershell/powershell'); require('codemirror/mode/python/python'); require('codemirror/mode/ruby/ruby'); require('codemirror/mode/sass/sass'); require('codemirror/mode/shell/shell'); require('codemirror/mode/sql/sql'); require('codemirror/mode/swift/swift'); require('codemirror/mode/twig/twig'); require('codemirror/mode/vue/vue'); require('codemirror/mode/xml/xml'); require('codemirror/mode/xquery/xquery'); require('codemirror/mode/yaml/yaml'); ``` ### v1.1.6 * All `PHP` files will be in the `root` and only `index.php`, `images`, `icons`, `svg`, `css`, `js`bundle files will be in the `public` subdir. ### v1.1.5 * Removed old `clone` button modal popup, using `Bootstrap` only * Double checked, all is using pure `Boostrap` * Added `toast` and save the `url` to the clipboard when you click on the `clone` button * Added `UglifyJs` and minimize the `css`. ### v1.1.3 * Moved to `webpack` * Using `Babel` ### v1.1.2 * Added twemoji's ### v1.1.1 * Format size was missing space (ugly) * Graph time was not using the ```config.ini``` * Fixed images to not show a html block span text and use now real image alt and title attributes in html * Graph was not using Bootstrap * Network wast not using Bootstrap ### v1.0.3 * Total bytes was not working with Twig 2 ### v1.0.2 * Add support for .gitmodules files at repository root * Updated to latest dependencies ### v1.0.1 * The minimum PHP version is 7.1 and PHPUNIT 7. ### v1.0.0 * Works with ```PHP 7.2``` ### v0.5.6 * The Markdown image links were not working. * Missed out the ```package.json``` from the previous release. ### v0.5.5 * Fixed PHPUNIT 6 ### v0.5.4 * Different submodule links for Gitlist and Github ### v0.5.3 * The markdown links are working right * Shows submodules ### v0.5.2 * Added all Bootsswatch themes (https://bootswatch.com/) * Removed default theme, kept only Bootstrap (though like over 10 themes now) * Removed PHP 5 support, only >= 7 * Upgraded Silex v1 to v2 * Upgraded Twig v1 to v2 * Upgraded Symfony/twig-bridge v2 to v3 * Upgraded Symfony/filesystem v2 to v3 * Upgraded Phpunit v4 to v6 * Moved from Showdown to Marked (more features) * For building requires (not required for the server): * NodeJs >= 8.9.0 * Bower * Grunt [//]: #@corifeus-footer --- [**P3X-GITLIST**](https://pages.corifeus.com/gitlist) Build v2.7.5-743 [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) ## P3X Sponsors [IntelliJ - The most intelligent Java IDE](https://www.jetbrains.com) [![JetBrains](https://cdn.corifeus.com/assets/svg/jetbrains-logo.svg)](https://www.jetbrains.com/) [![NoSQLBooster](https://cdn.corifeus.com/assets/png/nosqlbooster-70x70.png)](https://www.nosqlbooster.com/) [The Smartest IDE for MongoDB](https://www.nosqlbooster.com) [//]: #@corifeus-footer:endcomposer.json000066400000000000000000000010661516067327100136130ustar00rootroot00000000000000{ "name": "patrikx3/gitlist", "description": "An elegant git repository viewer", "minimum-stability": "stable", "autoload": { "psr-4": { "GitList\\": "src/" } }, "require": { "php": ">=7.1.0", "symfony/filesystem": ">=4", "symfony/twig-bridge": ">=4", "twig/twig": ">=2", "silex/silex": ">=2", "patrikx3/gitter": "^2.0" }, "require-dev": { "symfony/browser-kit": ">=4", "phpunit/phpunit": ">=7", "symfony/css-selector": ">=4" } } composer.lock000066400000000000000000002750031516067327100135760ustar00rootroot00000000000000{ "_readme": [ "This file locks the dependencies of your project to a known state", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "1a3e0f217a00c866cb5fdb29ba5b86a5", "content-hash": "0b00d3963cfedce5bb95b05fc1137135", "packages": [ { "name": "danielstjules/stringy", "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/danielstjules/Stringy.git", "reference": "df24ab62d2d8213bbbe88cc36fc35a4503b4bd7e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/danielstjules/Stringy/zipball/df24ab62d2d8213bbbe88cc36fc35a4503b4bd7e", "reference": "df24ab62d2d8213bbbe88cc36fc35a4503b4bd7e", "shasum": "" }, "require": { "php": ">=5.4.0", "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "type": "library", "autoload": { "psr-4": { "Stringy\\": "src/" }, "files": [ "src/Create.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Daniel St. Jules", "email": "danielst.jules@gmail.com", "homepage": "http://www.danielstjules.com" } ], "description": "A string manipulation library with multibyte support", "homepage": "https://github.com/danielstjules/Stringy", "keywords": [ "UTF", "helpers", "manipulation", "methods", "multibyte", "string", "utf-8", "utility", "utils" ], "time": "2017-06-12 01:10:27" }, { "name": "patrikx3/gitter", "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/patrikx3/gitter.git", "reference": "b0c79d6b500ad12cacdde8e56c99a5d8ec289737" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/patrikx3/gitter/zipball/b0c79d6b500ad12cacdde8e56c99a5d8ec289737", "reference": "b0c79d6b500ad12cacdde8e56c99a5d8ec289737", "shasum": "" }, "require": { "danielstjules/stringy": ">=3", "php": ">=7.1.0", "spatie/temporary-directory": "^1.1", "symfony/process": ">=4" }, "require-dev": { "mockery/mockery": ">=1", "phpunit/phpunit": ">=7", "symfony/filesystem": ">=4" }, "type": "library", "autoload": { "psr-0": { "Gitter": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-2-Clause" ], "authors": [ { "name": "Klaus Silveira", "email": "klaussilveira@php.net", "homepage": "http://www.klaussilveira.com/", "role": "Developer" }, { "name": "Patrik Laszlo", "email": "alabard@gmail.com", "homepage": "https://www.patrikx3.com/", "role": "Developer" } ], "description": "Gitter interacts with Git repositories with the latest version dependencies and PHP.", "homepage": "https://github.com/patrikx3/gitter", "keywords": [ "git", "vcs" ], "time": "2018-05-21 15:36:26" }, { "name": "pimple/pimple", "version": "v3.2.3", "source": { "type": "git", "url": "https://github.com/silexphp/Pimple.git", "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", "shasum": "" }, "require": { "php": ">=5.3.0", "psr/container": "^1.0" }, "require-dev": { "symfony/phpunit-bridge": "^3.2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.2.x-dev" } }, "autoload": { "psr-0": { "Pimple": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" } ], "description": "Pimple, a simple Dependency Injection Container", "homepage": "http://pimple.sensiolabs.org", "keywords": [ "container", "dependency injection" ], "time": "2018-01-21 07:42:36" }, { "name": "psr/container", "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "http://www.php-fig.org/" } ], "description": "Common Container Interface (PHP FIG PSR-11)", "homepage": "https://github.com/php-fig/container", "keywords": [ "PSR-11", "container", "container-interface", "container-interop", "psr" ], "time": "2017-02-14 16:28:37" }, { "name": "psr/log", "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "http://www.php-fig.org/" } ], "description": "Common interface for logging libraries", "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], "time": "2016-10-10 12:19:37" }, { "name": "silex/silex", "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/silexphp/Silex.git", "reference": "6bc31c1b8c4ef614a7115320fd2d3b958032f131" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/silexphp/Silex/zipball/6bc31c1b8c4ef614a7115320fd2d3b958032f131", "reference": "6bc31c1b8c4ef614a7115320fd2d3b958032f131", "shasum": "" }, "require": { "php": ">=7.1.3", "pimple/pimple": "^3.0", "symfony/event-dispatcher": "^4.0", "symfony/http-foundation": "^4.0", "symfony/http-kernel": "^4.0", "symfony/routing": "^4.0" }, "replace": { "silex/api": "self.version", "silex/providers": "self.version" }, "require-dev": { "doctrine/dbal": "^2.2", "monolog/monolog": "^1.4.1", "swiftmailer/swiftmailer": "^5", "symfony/asset": "^4.0", "symfony/browser-kit": "^4.0", "symfony/config": "^4.0", "symfony/css-selector": "^4.0", "symfony/debug": "^4.0", "symfony/doctrine-bridge": "^4.0", "symfony/dom-crawler": "^4.0", "symfony/expression-language": "^4.0", "symfony/finder": "^4.0", "symfony/form": "^4.0", "symfony/intl": "^4.0", "symfony/monolog-bridge": "^4.0", "symfony/options-resolver": "^4.0", "symfony/phpunit-bridge": "^3.2", "symfony/process": "^4.0", "symfony/security": "^4.0", "symfony/serializer": "^4.0", "symfony/translation": "^4.0", "symfony/twig-bridge": "^4.0", "symfony/validator": "^4.0", "symfony/var-dumper": "^4.0", "symfony/web-link": "^4.0", "twig/twig": "^2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.3.x-dev" } }, "autoload": { "psr-4": { "Silex\\": "src/Silex" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Igor Wiedler", "email": "igor@wiedler.ch" } ], "description": "The PHP micro-framework based on the Symfony Components", "homepage": "http://silex.sensiolabs.org", "keywords": [ "microframework" ], "time": "2018-04-20 05:17:01" }, { "name": "spatie/temporary-directory", "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/spatie/temporary-directory.git", "reference": "5e1799fa2297363ebfb4df296fea90afbd4ef9b7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/5e1799fa2297363ebfb4df296fea90afbd4ef9b7", "reference": "5e1799fa2297363ebfb4df296fea90afbd4ef9b7", "shasum": "" }, "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^6.3" }, "type": "library", "autoload": { "psr-4": { "Spatie\\TemporaryDirectory\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Alex Vanderbist", "email": "alex@spatie.be", "homepage": "https://spatie.be", "role": "Developer" } ], "description": "Easily create, use and destroy temporary directories", "homepage": "https://github.com/spatie/temporary-directory", "keywords": [ "spatie", "temporary-directory" ], "time": "2018-04-12 09:34:43" }, { "name": "symfony/debug", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", "reference": "4e7c98de67cc4171d4c986554e09a511da40f3d8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/debug/zipball/4e7c98de67cc4171d4c986554e09a511da40f3d8", "reference": "4e7c98de67cc4171d4c986554e09a511da40f3d8", "shasum": "" }, "require": { "php": "^7.1.3", "psr/log": "~1.0" }, "conflict": { "symfony/http-kernel": "<3.4" }, "require-dev": { "symfony/http-kernel": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", "time": "2018-05-16 09:05:32" }, { "name": "symfony/event-dispatcher", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", "reference": "63353a71073faf08f62caab4e6889b06a787f07b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/63353a71073faf08f62caab4e6889b06a787f07b", "reference": "63353a71073faf08f62caab4e6889b06a787f07b", "shasum": "" }, "require": { "php": "^7.1.3" }, "conflict": { "symfony/dependency-injection": "<3.4" }, "require-dev": { "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", "symfony/stopwatch": "~3.4|~4.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", "time": "2018-04-06 07:35:43" }, { "name": "symfony/filesystem", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", "reference": "7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/filesystem/zipball/7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04", "reference": "7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04", "shasum": "" }, "require": { "php": "^7.1.3", "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", "time": "2018-05-16 09:05:32" }, { "name": "symfony/http-foundation", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", "reference": "39f2b7c681fa6c323e43b8e30ccb6e714e7d2f00" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/39f2b7c681fa6c323e43b8e30ccb6e714e7d2f00", "reference": "39f2b7c681fa6c323e43b8e30ccb6e714e7d2f00", "shasum": "" }, "require": { "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { "symfony/expression-language": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", "time": "2018-05-16 09:05:32" }, { "name": "symfony/http-kernel", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", "reference": "aeae9c66976daf8a33c7be7c5e6314b39092b1b0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/aeae9c66976daf8a33c7be7c5e6314b39092b1b0", "reference": "aeae9c66976daf8a33c7be7c5e6314b39092b1b0", "shasum": "" }, "require": { "php": "^7.1.3", "psr/log": "~1.0", "symfony/debug": "~3.4|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", "symfony/http-foundation": "~3.4.4|~4.0.4", "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/config": "<3.4", "symfony/dependency-injection": "<3.4.5|<4.0.5,>=4", "symfony/var-dumper": "<3.4", "twig/twig": "<1.34|<2.4,>=2" }, "provide": { "psr/log-implementation": "1.0" }, "require-dev": { "psr/cache": "~1.0", "symfony/browser-kit": "~3.4|~4.0", "symfony/config": "~3.4|~4.0", "symfony/console": "~3.4|~4.0", "symfony/css-selector": "~3.4|~4.0", "symfony/dependency-injection": "^3.4.5|^4.0.5", "symfony/dom-crawler": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0", "symfony/process": "~3.4|~4.0", "symfony/routing": "~3.4|~4.0", "symfony/stopwatch": "~3.4|~4.0", "symfony/templating": "~3.4|~4.0", "symfony/translation": "~3.4|~4.0", "symfony/var-dumper": "~3.4|~4.0" }, "suggest": { "symfony/browser-kit": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", "symfony/var-dumper": "" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\HttpKernel\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", "time": "2018-05-21 14:02:31" }, { "name": "symfony/polyfill-ctype", "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" }, { "name": "Gert de Pagter", "email": "BackEndTea@gmail.com" } ], "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "ctype", "polyfill", "portable" ], "time": "2018-04-30 19:57:29" }, { "name": "symfony/polyfill-mbstring", "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { "php": ">=5.3.3" }, "suggest": { "ext-mbstring": "For best performance" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", "mbstring", "polyfill", "portable", "shim" ], "time": "2018-04-26 10:06:28" }, { "name": "symfony/process", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/process.git", "reference": "3621fa74d0576a6f89d63bc44fabd376711bd0b0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/process/zipball/3621fa74d0576a6f89d63bc44fabd376711bd0b0", "reference": "3621fa74d0576a6f89d63bc44fabd376711bd0b0", "shasum": "" }, "require": { "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Process Component", "homepage": "https://symfony.com", "time": "2018-05-16 09:05:32" }, { "name": "symfony/routing", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", "reference": "e8833b64b139926cbe1610d53722185e55c18e44" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/routing/zipball/e8833b64b139926cbe1610d53722185e55c18e44", "reference": "e8833b64b139926cbe1610d53722185e55c18e44", "shasum": "" }, "require": { "php": "^7.1.3" }, "conflict": { "symfony/config": "<3.4", "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, "require-dev": { "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", "symfony/http-foundation": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, "suggest": { "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", "symfony/dependency-injection": "For loading routes from a service", "symfony/expression-language": "For using expression matching", "symfony/http-foundation": "For using a Symfony Request object", "symfony/yaml": "For using the YAML loader" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Routing\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Routing Component", "homepage": "https://symfony.com", "keywords": [ "router", "routing", "uri", "url" ], "time": "2018-05-16 14:21:07" }, { "name": "symfony/twig-bridge", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", "reference": "5207df6379bbdffba0494f8814792b3724886d42" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5207df6379bbdffba0494f8814792b3724886d42", "reference": "5207df6379bbdffba0494f8814792b3724886d42", "shasum": "" }, "require": { "php": "^7.1.3", "twig/twig": "^1.35|^2.4.4" }, "conflict": { "symfony/console": "<3.4", "symfony/form": "<3.4.9|<4.0.9,>=4.0" }, "require-dev": { "symfony/asset": "~3.4|~4.0", "symfony/console": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0", "symfony/form": "^3.4.9|^4.0.9", "symfony/http-foundation": "~3.4|~4.0", "symfony/http-kernel": "~3.4|~4.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~3.4|~4.0", "symfony/security": "~3.4|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/stopwatch": "~3.4|~4.0", "symfony/templating": "~3.4|~4.0", "symfony/translation": "~3.4|~4.0", "symfony/var-dumper": "~3.4|~4.0", "symfony/web-link": "~3.4|~4.0", "symfony/workflow": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, "suggest": { "symfony/asset": "For using the AssetExtension", "symfony/expression-language": "For using the ExpressionExtension", "symfony/finder": "", "symfony/form": "For using the FormExtension", "symfony/http-kernel": "For using the HttpKernelExtension", "symfony/routing": "For using the RoutingExtension", "symfony/security": "For using the SecurityExtension", "symfony/stopwatch": "For using the StopwatchExtension", "symfony/templating": "For using the TwigEngine", "symfony/translation": "For using the TranslationExtension", "symfony/var-dumper": "For using the DumpExtension", "symfony/web-link": "For using the WebLinkExtension", "symfony/yaml": "For using the YamlExtension" }, "type": "symfony-bridge", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Bridge\\Twig\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", "time": "2018-05-11 15:58:37" }, { "name": "twig/twig", "version": "v2.4.8", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", "reference": "7b604c89da162034bdf4bb66310f358d313dd16d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/twigphp/Twig/zipball/7b604c89da162034bdf4bb66310f358d313dd16d", "reference": "7b604c89da162034bdf4bb66310f358d313dd16d", "shasum": "" }, "require": { "php": "^7.0", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { "psr/container": "^1.0", "symfony/debug": "^2.7", "symfony/phpunit-bridge": "^3.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.4-dev" } }, "autoload": { "psr-0": { "Twig_": "lib/" }, "psr-4": { "Twig\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com", "homepage": "http://fabien.potencier.org", "role": "Lead Developer" }, { "name": "Armin Ronacher", "email": "armin.ronacher@active-4.com", "role": "Project Founder" }, { "name": "Twig Team", "homepage": "http://twig.sensiolabs.org/contributors", "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", "homepage": "http://twig.sensiolabs.org", "keywords": [ "templating" ], "time": "2018-04-02 09:24:19" } ], "packages-dev": [ { "name": "doctrine/instantiator", "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "^6.2.3", "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", "homepage": "http://ocramius.github.com/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://github.com/doctrine/instantiator", "keywords": [ "constructor", "instantiate" ], "time": "2017-07-22 11:58:36" }, { "name": "myclabs/deep-copy", "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { "php": "^5.6 || ^7.0" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" }, "files": [ "src/DeepCopy/deep_copy.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", "keywords": [ "clone", "copy", "duplicate", "object", "object graph" ], "time": "2017-10-19 19:58:43" }, { "name": "phar-io/manifest", "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", "phar-io/version": "^1.0.1", "php": "^5.6 || ^7.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "time": "2017-03-05 18:14:27" }, { "name": "phar-io/version", "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", "shasum": "" }, "require": { "php": "^5.6 || ^7.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Library for handling version information and constraints", "time": "2017-03-05 17:38:23" }, { "name": "phpdocumentor/reflection-common", "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { "php": ">=5.5" }, "require-dev": { "phpunit/phpunit": "^4.6" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ "src" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jaap van Otterdijk", "email": "opensource@ijaap.nl" } ], "description": "Common reflection classes used by phpdocumentor to reflect the code structure", "homepage": "http://www.phpdoc.org", "keywords": [ "FQSEN", "phpDocumentor", "phpdoc", "reflection", "static analysis" ], "time": "2017-09-11 18:02:19" }, { "name": "phpdocumentor/reflection-docblock", "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "reference": "94fd0001232e47129dd3504189fa1c7225010d08" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", "reference": "94fd0001232e47129dd3504189fa1c7225010d08", "shasum": "" }, "require": { "php": "^7.0", "phpdocumentor/reflection-common": "^1.0.0", "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { "doctrine/instantiator": "~1.0.5", "mockery/mockery": "^1.0", "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.x-dev" } }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "me@mikevanriel.com" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "time": "2017-11-30 07:14:17" }, { "name": "phpdocumentor/type-resolver", "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { "php": "^5.5 || ^7.0", "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { "mockery/mockery": "^0.9.4", "phpunit/phpunit": "^5.2||^4.8.24" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "me@mikevanriel.com" } ], "time": "2017-07-14 14:27:02" }, { "name": "phpspec/prophecy", "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.7.x-dev" } }, "autoload": { "psr-0": { "Prophecy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" }, { "name": "Marcello Duarte", "email": "marcello.duarte@gmail.com" } ], "description": "Highly opinionated mocking framework for PHP 5.3+", "homepage": "https://github.com/phpspec/prophecy", "keywords": [ "Double", "Dummy", "fake", "mock", "spy", "stub" ], "time": "2018-04-18 13:57:24" }, { "name": "phpunit/php-code-coverage", "version": "6.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/52187754b0eed0b8159f62a6fa30073327e8c2ca", "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", "php": "^7.1", "phpunit/php-file-iterator": "^1.4.2", "phpunit/php-text-template": "^1.2.1", "phpunit/php-token-stream": "^3.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^3.1", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { "phpunit/phpunit": "^7.0" }, "suggest": { "ext-xdebug": "^2.6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ "coverage", "testing", "xunit" ], "time": "2018-04-29 14:59:09" }, { "name": "phpunit/php-file-iterator", "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ], "time": "2017-11-27 13:52:08" }, { "name": "phpunit/php-text-template", "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ], "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ], "time": "2018-02-01 13:07:23" }, { "name": "phpunit/php-token-stream", "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace", "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": "^7.1" }, "require-dev": { "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ "tokenizer" ], "time": "2018-02-01 13:16:43" }, { "name": "phpunit/phpunit", "version": "7.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", "reference": "ca64dba53b88aba6af32aebc6b388068db95c435" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ca64dba53b88aba6af32aebc6b388068db95c435", "reference": "ca64dba53b88aba6af32aebc6b388068db95c435", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "myclabs/deep-copy": "^1.6.1", "phar-io/manifest": "^1.0.1", "phar-io/version": "^1.0", "php": "^7.1", "phpspec/prophecy": "^1.7", "phpunit/php-code-coverage": "^6.0.1", "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^2.0", "phpunit/phpunit-mock-objects": "^6.1.1", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^1.0", "sebastian/version": "^2.0.1" }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-xdebug": "*", "phpunit/php-invoker": "^2.0" }, "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { "dev-master": "7.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], "time": "2018-04-29 15:09:19" }, { "name": "phpunit/phpunit-mock-objects", "version": "6.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/70c740bde8fd9ea9ea295be1cd875dd7b267e157", "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.5", "php": "^7.1", "phpunit/php-text-template": "^1.2.1", "sebastian/exporter": "^3.1" }, "require-dev": { "phpunit/phpunit": "^7.0" }, "suggest": { "ext-soap": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "6.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Mock Object library for PHPUnit", "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", "keywords": [ "mock", "xunit" ], "time": "2018-04-11 04:50:36" }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { "php": "^5.6 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "time": "2017-03-04 06:30:41" }, { "name": "sebastian/comparator", "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "ed5fd2281113729f1ebcc64d101ad66028aeb3d5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ed5fd2281113729f1ebcc64d101ad66028aeb3d5", "reference": "ed5fd2281113729f1ebcc64d101ad66028aeb3d5", "shasum": "" }, "require": { "php": "^7.1", "sebastian/diff": "^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { "phpunit/phpunit": "^7.1" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], "time": "2018-04-18 13:33:00" }, { "name": "sebastian/diff", "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8", "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { "phpunit/phpunit": "^7.0", "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff", "udiff", "unidiff", "unified diff" ], "time": "2018-02-01 13:45:15" }, { "name": "sebastian/environment", "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "shasum": "" }, "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^6.1" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.1.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ], "time": "2017-07-01 08:51:00" }, { "name": "sebastian/exporter", "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", "shasum": "" }, "require": { "php": "^7.0", "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.1.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "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" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "http://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "time": "2017-04-03 13:19:02" }, { "name": "sebastian/global-state", "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "time": "2017-04-27 15:39:26" }, { "name": "sebastian/object-enumerator", "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { "php": "^7.0", "sebastian/object-reflector": "^1.1.1", "sebastian/recursion-context": "^3.0" }, "require-dev": { "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "time": "2017-08-03 12:35:26" }, { "name": "sebastian/object-reflector", "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", "reference": "773f97c67f28de00d397be301821b06708fca0be" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", "reference": "773f97c67f28de00d397be301821b06708fca0be", "shasum": "" }, "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", "time": "2017-03-29 09:07:27" }, { "name": "sebastian/recursion-context", "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "shasum": "" }, "require": { "php": "^7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "time": "2017-03-03 06:23:57" }, { "name": "sebastian/resource-operations", "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", "shasum": "" }, "require": { "php": ">=5.6.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "time": "2015-07-28 20:34:47" }, { "name": "sebastian/version", "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { "php": ">=5.6" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03 07:35:21" }, { "name": "symfony/browser-kit", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", "reference": "c43bfa0182363b3fd64331b5e64e467349ff4670" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c43bfa0182363b3fd64331b5e64e467349ff4670", "reference": "c43bfa0182363b3fd64331b5e64e467349ff4670", "shasum": "" }, "require": { "php": "^7.1.3", "symfony/dom-crawler": "~3.4|~4.0" }, "require-dev": { "symfony/css-selector": "~3.4|~4.0", "symfony/process": "~3.4|~4.0" }, "suggest": { "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\BrowserKit\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", "time": "2018-03-19 22:35:49" }, { "name": "symfony/css-selector", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", "reference": "0383a1a4eb1ffcac28719975d3e01bfa14be8ab3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/css-selector/zipball/0383a1a4eb1ffcac28719975d3e01bfa14be8ab3", "reference": "0383a1a4eb1ffcac28719975d3e01bfa14be8ab3", "shasum": "" }, "require": { "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jean-François Simon", "email": "jeanfrancois.simon@sensiolabs.com" }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", "time": "2018-05-11 15:58:37" }, { "name": "symfony/dom-crawler", "version": "v4.0.10", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", "reference": "cf13fe774cabf4d32e8e234ec6efe7821e8b6ec1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/cf13fe774cabf4d32e8e234ec6efe7821e8b6ec1", "reference": "cf13fe774cabf4d32e8e234ec6efe7821e8b6ec1", "shasum": "" }, "require": { "php": "^7.1.3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { "symfony/css-selector": "~3.4|~4.0" }, "suggest": { "symfony/css-selector": "" }, "type": "library", "extra": { "branch-alias": { "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\DomCrawler\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", "time": "2018-05-01 23:00:51" }, { "name": "theseer/tokenizer", "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": "^7.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "time": "2017-04-07 12:08:54" }, { "name": "webmozart/assert", "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", "reference": "0df1908962e7a3071564e857d86874dad1ef204a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", "reference": "0df1908962e7a3071564e857d86874dad1ef204a", "shasum": "" }, "require": { "php": "^5.3.3 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.6", "sebastian/version": "^1.0.1" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.3-dev" } }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" } ], "description": "Assertions to validate method input/output with nice error messages.", "keywords": [ "assert", "check", "validate" ], "time": "2018-01-29 19:49:41" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=7.1.0" }, "platform-dev": [] } config.example.ini000066400000000000000000000033321516067327100144670ustar00rootroot00000000000000[git] client = '/usr/bin/git' ; Your git executable path default_branch = 'master' ; Default branch when HEAD is detached repositories[] = '/var/git/' ; Path to your repositories ; If you wish to add more repositories, just add a new line ; WINDOWS USERS ;client = '"C:\Program Files (x86)\Git\bin\git.exe"' ; Your git executable path ;repositories[] = 'C:\Path\to\Repos\' ; Path to your repositories ; You can hide repositories from GitList, just copy this for each repository you want to hide ; hidden[] = '/home/git/repositories/BetaTest' [app] debug = false cache = true ; big files can block the browser in code mirror, so there is a limit codemirror_full_limit = 48 [clone_button] ; ssh remote show_ssh_remote = true ; display remote URL for SSH ssh_user = 'git' ; user to use for cloning via SSH ; http remote show_http_remote = true; display remote URL for HTTP use_https = true ; generate URL with https:// ; if cloning via HTTP is triggered using virtual dir (e.g. https://example.com/git/repo.git) ; it there is a subdir, start with string and end with trailing slash ; eg git_clone_subdir = 'subdir/' git_clone_subdir = '' http_user = '' ; user to use for cloning via HTTP (default: none) http_user_dynamic = false ; when enabled, http_user is set to $_SERVER['PHP_AUTH_USER'] ; If you need to specify custom filetypes for certain extensions, do this here [filetypes] ; extension = type ; dist = xml ; If you need to set file types as binary or not, do this here [binary_filetypes] ; extension = true ; svh = false ; map = true ; set the timezone [date] ; timezone = UTC ; format = 'd/m/Y H:i:s' ; custom avatar service [avatar] ; url = '//gravatar.com/avatar/' ; query[] = 'd=identicon'gitlist.iml000066400000000000000000000015221516067327100132500ustar00rootroot00000000000000 grunt/000077500000000000000000000000001516067327100122255ustar00rootroot00000000000000grunt/less.js000066400000000000000000000104151516067327100135320ustar00rootroot00000000000000const fs = require('fs'); const fsExtra = require('fs-extra'); const glob = require('glob'); const crypto = require('crypto'); const path = require('path'); const cwd = path.resolve(`${process.cwd()}`) const cssPostfixFilename = `${cwd}/src/css-postfix`; //let lessLastHash = fs.readFileSync(cssPostfixFilename, 'utf8').toString(); let lessLastHash; let lessFiles; const filesLessCache = `${cwd}/build/less/file-less.json`; //const filesLessCacheBuild = `${cwd}/public/generated/css`; const lessSettings = (grunt) => { return { options: { sourceMap: true, compress: true, }, get files() { const files = glob.sync(`${cwd}/public/less/**/*.*`) let string = '' for (let filename of files) { string += fs.readFileSync(filename, 'utf8') } const lessHash = crypto.createHash('sha256').update(string).digest("hex"); if (lessLastHash === lessHash) { grunt.log.writeln(`less hash is the same - ${lessHash}`) return lessFiles }/* else if (fs.existsSync(filesLessCacheBuild) && fs.existsSync(filesLessCache) && fs.readFileSync(cssPostfixFilename, 'utf8').toString() === lessHash) { grunt.log.writeln(`less hash is the same in different process, using file less cache - ${lessHash}`) return fs.readFileSync(filesLessCache, 'utf8').toString(); }*/ grunt.log.writeln(`less hash generating new build - ${lessHash}`) lessLastHash = lessHash; fs.writeFileSync(cssPostfixFilename, lessHash) grunt.log.writeln('The css postfix file has been saved!'); const generateLessFiles = () => { const themeDir = './public/less/theme'; const filesLess = {} const root = './node_modules/bootswatch'; const watches = fs.readdirSync(root); const themes = [ 'default', 'solar', ]; const excluded = ['fonts']; // css with random const themeCss = { 'bootstrap-default': `generated/css/bootstrap-default.${lessHash}.css`, 'bootstrap-solar': `generated/css/bootstrap-solar.${lessHash}.css`, } for (let path of watches) { const stat = fs.statSync(`${root}/${path}`); if (stat.isDirectory() && !excluded.includes(path)) { themes.push(path); themeCss[`bootstrap-${path}`] = `generated/css/bootstrap-${path}.${lessHash}.css`; } } // -- css with random // less with random fsExtra.ensureDirSync(themeDir); for (let theme of themes) { const less = `${themeDir}/${theme}.less`; if (theme === 'default') { fs.writeFileSync(less, ` @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../default"; `) } else if (theme === 'solar') { fs.writeFileSync(less, ` @import "../../../node_modules/bootstrap/less/bootstrap"; @import "solar/variables"; @import "solar/bootswatch"; @import "../default"; `) } else { fs.writeFileSync(less, ` @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/${theme}/variables"; @import "../../../node_modules/bootswatch/${theme}/bootswatch"; @import "../default"; `) } // console.log(less) filesLess[`public/generated/css/bootstrap-${theme}.${lessHash}.css`] = less; } // -- less with random fs.writeFileSync(`./public/js/themes.js`, ` const themes = ${JSON.stringify(themeCss, null, 4)}; module.exports = themes; `); fsExtra.outputJsonSync(filesLessCache, filesLess) return filesLess // grunt.log.writeln(JSON.stringify(filesLess, null, 2)) } lessFiles = generateLessFiles(); return lessFiles; } }; } module.exports.lessSettings = lessSettings;package.json000066400000000000000000000044041516067327100133560ustar00rootroot00000000000000{ "name": "p3x-gitlist", "version": "2.7.5-743", "corifeus": { "postfix": "", "prefix": "p3x-", "publish": false, "type": "p3x", "opencollective": false, "cdn": true, "icon": "fas fa-code", "code": "Spawn", "nodejs": "v10.1.0", "reponame": "gitlist", "build": true }, "scripts": { "build": "grunt && webpack --production", "webpack-watch": "webpack --watch", "less-watch": "grunt watch:less", "watch": "grunt && concurrently \"webpack --watch\" \"grunt watch:less\"" }, "description": "🤖 P3X Gitlist", "main": "index.js", "repository": "https://github.com/patrikx3/gitlist", "author": "patrikx3 ", "license": "MIT", "devDependencies": { "bootswatch": "^3.3.7", "concurrently": "^3.5.1", "corifeus-builder": "^1.8.9-414", "corifeus-utils": "^1.2.66-383", "css-loader": "^0.28.11", "extract-text-webpack-plugin": "^4.0.0-beta.0", "file-loader": "^1.1.11", "fs-extra": "^6.0.1", "glob": "^7.1.2", "grunt": "^1.0.2", "grunt-contrib-less": "^1.4.1", "html-webpack-plugin": "^3.2.0", "less-loader": "^4.1.0", "style-loader": "^0.21.0", "uglifyjs-webpack-plugin": "^1.2.5", "url-loader": "^1.0.1", "on-build-webpack": "^0.1.0", "webpack": "^4.8.3", "webpack-cli": "^2.1.3" }, "engines": { "node": ">=8.9.0" }, "homepage": "https://pages.corifeus.com/gitlist", "dependencies": { "@fortawesome/fontawesome": "^1.1.8", "@fortawesome/fontawesome-free-brands": "^5.0.13", "@fortawesome/fontawesome-free-regular": "^5.0.13", "@fortawesome/fontawesome-free-solid": "^5.0.13", "bootstrap": "^3.3.7", "codemirror": "^5.37.0", "highlight.js": "^9.12.0", "jquery": "^3.3.1", "jquery.redirect": "^1.1.1", "js-cookie": "^2.2.0", "js-htmlencode": "^0.3.0", "list.js": "^1.5.0", "lodash": "^4.17.10", "marked": "^0.3.19", "php-date": "^2.1.1", "raphael": "^2.2.7", "snackbarjs": "^1.1.0", "twemoji": "^2.5.1" } }phpunit.xml000066400000000000000000000011661516067327100133030ustar00rootroot00000000000000 ./src/ ./tests/ public/000077500000000000000000000000001516067327100123445ustar00rootroot00000000000000public/.htaccess000066400000000000000000000005131516067327100141410ustar00rootroot00000000000000 Options -MultiViews +SymLinksIfOwnerMatch RewriteEngine On #RewriteBase /path/to/gitlist/ RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L,NC] order allow,deny deny from all public/img/000077500000000000000000000000001516067327100131205ustar00rootroot00000000000000public/img/favicon.png000066400000000000000000000015641516067327100152610ustar00rootroot00000000000000‰PNG  IHDR D¤ŠÆ\PLTEçH%çH%çH%æH%ðK&øN(ìJ%óL'øN(ùN(øN(ùN(ùN(òK&ùM'ëJ&ïK&øN(ùN(úO(óL'øN(ïK&ùN(ðK&ùN(ùN(øN(øN(ëI%øN(ñL&ûO(õM'êI%èI%úO(úO(÷N'êI%øN(êI%úO(õM'öM'ûO(æH$æH$ôM'öM'óL'ôM'ìJ%ôM'õM'õM'ðK&ëI%íJ&óL(òL&ïJ'îJ'ùN(ôM'ñK&ïK&ûO(îJ%úO(ûO(òL&óL(åG%çH&ôM'öN'øN(øN(÷N'õM'öM'üO(üO(õM'õM'õM'ùN(ùN(ùN(ôM'öM'ùN(òL&òL&üO(æH$åG$æH$æH$æH$÷M'÷N(úN(ùN(üO(éH%úO(øN(÷N'õM'öM'ôM'ûO(óL(q`åÝatRNSýþþþÈàµSZÁ£ÝÑ^k¸{ÉYÇ –ëaÇa¨æó‚ aÜÒˆSøîŠ›³„ ÑÓÒ.1®³’DÑÔDâB69MèÛBCBCB`CJPCBaWCaaTGF]¥Äê/fIDATxÚuÑgoÂ0`KÝ{ï½÷Þ{ï=BÛ>”¦`Éÿ—jsŠÌE­?ÙΣ×w¶fÖžø ý®ëþ|þ :›Ò.AÐøæ"ÐÆD´41&8蕲÷¤¬``TI)[;€‘a_0U*©E·Ù×ëgHXÍf•ÒæPã×aÁ}V/“1Ô Ì*5à5“!¡d]e¨Ò‚^!ð–ËXQR^bÝ ýÝ#¾”*d)«íó…8÷rzùq .‹+L’xž—$4RVMìX\z^AFÂ$ÈFŠ3Ï I98ì9ùJOÞ …º—Ôâ¦ãq| €f*#N` À˜î6I"6cn ˜žõ3" P æÍaþ‹¼~¥Ëf¿AS¿…6cieufzüŒDœ&v àÝ> x·/ø Ø™>ƒƒ`Æ8fìã€íÝ-~ó z †´¾:†IEND®B`‚public/index.php000077500000000000000000000014441516067327100141720ustar00rootroot00000000000000get('date', 'timezone')) { date_default_timezone_set($config->get('date', 'timezone')); } $app = require '../boot.php'; $app->run(); public/js/000077500000000000000000000000001516067327100127605ustar00rootroot00000000000000public/js/browser.js000066400000000000000000000067071516067327100150130ustar00rootroot00000000000000$(function() { const menu = $('#p3x-gitlist-branch-list-container'); if (menu.length > 0) { // const menuResponsive = require('./menu-responsive') // menuResponsive({ // menuList: $('#p3x-gitlist-branch-list-dropdown-menu'), // }) const List = require('list.js') const mainId = 'p3x-gitlist-branch-list' const branchListId = 'p3x-gitlist-list-branch' const tagListId = 'p3x-gitlist-list-tag' const debounce = require('lodash/debounce') let paths = window.gitlist.getPaths(); let slice = 4 if (window.gitlist.browse_type === 'tree') { slice = 3 } paths = paths.slice(slice); let path = paths.join('/') if (path !== '') { path = `/${path}` } const baseUrl = `${window.gitlist.basepath}/${window.gitlist.repo}` const search_query = window.gitlist.search_query; const urls = { tree: (options) => { return `${baseUrl}/${options.checkout}`; }, commits: (options) => { return `${baseUrl}/commits/${options.checkout}${path}`; }, commit: (options) => { return `${baseUrl}/commits/${options.checkout}${path}`; }, stats: (options) => { return `${baseUrl}/stats/${options.checkout}${path}`; }, network: (options) => { return `${baseUrl}/network/${options.checkout}${path}`; }, blob: (options) => { return `${baseUrl}/blob/${options.checkout}${path}`; }, blame: (options) => { return `${baseUrl}/blame/${options.checkout}${path}`; }, treegraph: (options) => { return `${baseUrl}/treegraph/${options.checkout}${path}`; }, search: (options) => { return { url: `${baseUrl}/tree/${options.checkout}/search?query=${search_query}`, post: true, } }, searchcommits: (options) => { return { url: `${baseUrl}/commits/${options.checkout}/search?query=${search_query}`, post: true, }; }, } window.gitlist.browserClick = (options) => { let result = urls[window.gitlist.browse_type](options); if (typeof result === 'string') { result = { url: result } } if (!result.hasOwnProperty('post')) { location = result.url; } else { $.redirect(result.url); } } if ($(`#${mainId}`).length) { const listBranchOptions = { valueNames: ['item'], indexAsync: true, }; const branchList = new List(branchListId, listBranchOptions); const tagList = new List(tagListId, listBranchOptions); const input = $('#p3x-gitlist-branch-list-search'); const debouncedKeyup = debounce(() => { const search = input.val().trim(); branchList.search(search) if (tagList.hasOwnProperty('search')) { tagList.search(search) } }, 250) input.keyup(debouncedKeyup) } } }) public/js/bundle.js000066400000000000000000000063451516067327100145770ustar00rootroot00000000000000window.gitlist.codemirrorTheme = { light: 'idea', dark: 'dracula', } require('codemirror/lib/codemirror.css') require(`codemirror/theme/idea.css`) require(`codemirror/theme/dracula.css`) //require('../less/style.less') const fontawesome = require('@fortawesome/fontawesome').default //console.log(fontawesome); //console.log(fontawesome.default); const faSolid = require('@fortawesome/fontawesome-free-solid')['default'] const faRegular = require('@fortawesome/fontawesome-free-regular')['default'] const faBrands = require('@fortawesome/fontawesome-free-brands')['default'] fontawesome.library.add(faSolid) fontawesome.library.add(faRegular) fontawesome.library.add(faBrands) window.gitlist.snapckbarLongTimeout = 10000; global.jQuery = require('jquery') global.$ = global.jQuery; require('snackbarjs'); require('jquery.redirect'); require('bootstrap'); global.marked = require('marked') global.htmlEncode = require('js-htmlencode') global.CodeMirror = require('codemirror'); require('codemirror/addon/selection/active-line.js') require('codemirror/addon/mode/simple'); require('codemirror/addon/mode/multiplex'); require('codemirror/mode/cmake/cmake'); require('codemirror/mode/clike/clike'); require('codemirror/mode/css/css'); require('codemirror/mode/dockerfile/dockerfile'); require('codemirror/mode/go/go'); require('codemirror/mode/handlebars/handlebars'); require('codemirror/mode/htmlmixed/htmlmixed'); require('codemirror/mode/javascript/javascript'); require('codemirror/mode/jsx/jsx'); require('codemirror/mode/perl/perl'); require('codemirror/mode/php/php'); require('codemirror/mode/powershell/powershell'); require('codemirror/mode/python/python'); require('codemirror/mode/properties/properties'); require('codemirror/mode/ruby/ruby'); require('codemirror/mode/sass/sass'); require('codemirror/mode/shell/shell'); require('codemirror/mode/vbscript/vbscript'); require('codemirror/mode/groovy/groovy'); require('codemirror/mode/erlang/erlang'); require('codemirror/mode/ecl/ecl'); require('codemirror/mode/coffeescript/coffeescript'); require('codemirror/mode/clojure/clojure'); require('codemirror/mode/diff/diff'); require('codemirror/mode/smalltalk/smalltalk'); require('codemirror/mode/rust/rust'); require('codemirror/mode/lua/lua'); require('codemirror/mode/haskell/haskell'); require('codemirror/mode/markdown/markdown'); require('codemirror/mode/scheme/scheme'); require('codemirror/mode/r/r'); require('codemirror/mode/rst/rst'); require('codemirror/mode/ntriples/ntriples'); require('codemirror/mode/pascal/pascal'); require('codemirror/mode/sql/sql'); require('codemirror/mode/swift/swift'); require('codemirror/mode/twig/twig'); require('codemirror/mode/vue/vue'); require('codemirror/mode/xml/xml'); require('codemirror/mode/xquery/xquery'); require('codemirror/mode/yaml/yaml'); require('eve-raphael/eve.js'); global.Raphael = require('raphael') global.twemoji = require('twemoji') global.twemoji.base = 'generated/twemoji/'; require('./network.js') require('./gitgraph.js/gitgraph.css') require('./gitgraph.js/gitgraph.js') require('./treegraph') require('./markdown') require('./clone-buttons') require('./paginate') require('./browser') require('./index.js') require('./file') require('./theme-switcher.js') require('./commit') require('./global') public/js/clone-buttons.js000066400000000000000000000033221516067327100161120ustar00rootroot00000000000000$(function() { const cloneButtonSSH = $('#clone-button-ssh'); const cloneButtonHTTP = $('#clone-button-http'); const cloneInputSSH = $('#clone-input-ssh'); const cloneInputHTTP = $('#clone-input-http'); const debounce = require('lodash/debounce') const copy = debounce(($input) => { const input = $input[0]; input.select() document.execCommand("Copy"); $.snackbar({ htmlAllowed: true, content: ` This URL is in your clipboard:
${input.value}` }); }, 250); const copyCloneInputSSH = () => { copy(cloneInputSSH) } const copyCloneInputHTTP = () => { copy(cloneInputHTTP) } cloneInputSSH.click(copyCloneInputSSH) cloneInputHTTP.click(copyCloneInputHTTP) let cloneButtonSSHInit = false; cloneButtonSSH.click(function() { if(cloneButtonSSH.hasClass('active')) { return; } if (cloneButtonSSHInit) { copyCloneInputSSH(); } cloneButtonSSHInit = true; cloneButtonSSH.addClass('active'); cloneInputSSH.show(); cloneButtonHTTP.removeClass('active'); cloneInputHTTP.hide(); }); let cloneButtonHTTPInit = false; cloneButtonHTTP.click(function() { if(cloneButtonHTTP.hasClass('active')) { return; } if (cloneButtonHTTPInit) { copyCloneInputHTTP() } cloneButtonHTTPInit = true; cloneButtonHTTP.addClass('active'); cloneInputHTTP.show(); cloneButtonSSH.removeClass('active'); cloneInputSSH.hide(); }); cloneButtonSSH.click(); cloneButtonHTTP.click(); }) public/js/commit.js000066400000000000000000000026171516067327100146140ustar00rootroot00000000000000$(() => { const diffEditors = $('.p3x-gitlist-commit-diff'); let deferScroll; if (diffEditors) { for (let diffEditor of diffEditors) { const $editableHover = $('#' + diffEditor.dataset.diffId); const editableHover = $editableHover.get(0); $editableHover.one('click', () => { clearTimeout(deferScroll) setTimeout(() => { window.gitlist.scrollIntoView(document.getElementById(diffEditor.dataset.diffRef)) }, 0) $editableHover.find('.panel-body').html(' Loading the diff ...') const value = JSON.parse(diffEditor.innerText).toString() diffEditor.remove(); const editor = CodeMirror(function (node) { editableHover.parentNode.replaceChild(node, editableHover); }, { styleActiveLine: true, styleSelectedText: true, value: value, lineNumbers: false, matchBrackets: true, lineWrapping: false, readOnly: true, mode: 'text/x-diff', theme: window.gitlist.getActualThemeCodemirror(), }); window.gitlist.diffEditors.push(editor) }) } } })public/js/file.js000066400000000000000000000232121516067327100142350ustar00rootroot00000000000000$(function() { const sourceCode = $('#p3x-gitlist-file-editor'); if (sourceCode.length) { const commit = window.gitlist.commit; const branches = window.gitlist.branches; let originalCode = ''; let disableFull = false; const Cookies = require('js-cookie') const cookieName = 'p3x-gitlist-codemirror-size' const currentSizing = Cookies.get(cookieName) const codeCodeMirroNormal = $('#p3x-gitlist-file-codemirror'); const codeCodeMirrorBig = $('#p3x-gitlist-file-codemirror-exceeded') let value = sourceCode.text(); const maxSize = window.gitlist.codemirror_full_limit; const size = Math.ceil(value.length / 1024); const createCodeMirror = () => { if (size > maxSize) { disableFull = true; codeCodeMirroNormal.hide(); codeCodeMirrorBig.show(); } else { codeCodeMirroNormal.show(); } const mode = sourceCode.attr('language'); const pre = sourceCode.get(0); const codeMirror = $('.CodeMirror'); const buttonScroll = $('#p3x-gitlist-file-button-scroll'); const buttonFull = $('#p3x-gitlist-file-button-full'); const buttonEdit = $('#p3x-gitlist-file-button-edit'); const buttonEditCancel = $('#p3x-gitlist-file-button-edit-cancel'); const buttonEditSave = $('#p3x-gitlist-file-button-edit-save') const codeMirrorHeight = 300; buttonEditCancel.hide(); buttonEditSave.hide(); buttonEdit.click(() => { if (!branches.includes(commit)) { let branchInfo; if (branches.length === 1) { branchInfo = `Only the ${branches.join(', ')} branch is editable.` } else { branchInfo = `Only the ${branches.join(', ')} branches are editable.` } $.snackbar({ htmlAllowed: true, content: `This commit ${commit} is not editable.
${branchInfo} `, timeout: window.gitlist.snapckbarLongTimeout, }) return; } // buttonEditRow.show(); buttonEdit.hide(); buttonEditCancel.show(); buttonEditSave.show(); gitlist.viewer.setOption('readOnly', false) originalCode = gitlist.viewer.getValue() gitlist.viewer.focus(); $.snackbar({ content: `Editing`, }) }) const validateCodeIsSame = (snack = true) => { value = gitlist.viewer.getValue(); if (originalCode === value) { if (snack) { $.snackbar({ content: 'The code has not changed. No saving.', }) } return true; } return false; } const close = () => { buttonEdit.show(); buttonEditSave.hide(); buttonEditCancel.hide(); gitlist.viewer.setOption('readOnly', true) } buttonEditCancel.click(() => { if (!validateCodeIsSame(false)) { gitlist.viewer.setValue(originalCode) $.snackbar({ htmlAllowed: true, content: 'The changes are reverted.', }) } close(); }) let filename = window.gitlist.getPaths(); filename = filename.slice(4).join('/'); const errorHandler = (e) => { $.snackbar({ htmlAllowed: true, content: e.message, timeout: window.gitlist.snapckbarLongTimeout, }) console.error(e); } const commitModal = $('#p3x-gitlist-modal-commit'); buttonEditSave.click(async () => { if (validateCodeIsSame()) { return; } commitModal.modal('show') }) const commitInputName = $('#p3x-gitlist-modal-commit-name'); const commitInputEmail = $('#p3x-gitlist-modal-commit-email'); const commitInputComment = $('#p3x-gitlist-modal-commit-comment'); const commitForm = $('#p3x-gitlist-modal-commit-form'); const inputs = { name: commitInputName, email: commitInputEmail, comment: commitInputComment, } for(let inputKey in inputs) { const input = inputs[inputKey] const cookieName = `p3x-gitlist-commit-${inputKey}`; const cookie = Cookies.get(cookieName) if (cookie) { input.val(cookie.trim()); } input.change(() => { const val = input.val().trim(); Cookies.set(cookieName, val); input.val(val); }) } const commitCommitPushButton = $('#p3x-gitlist-modal-commit-push') commitCommitPushButton.click( async () => { if (validateCodeIsSame()) { return; } if(commitForm[0].checkValidity() === false) { $.snackbar({ content: 'The commit form data is invalid..' }) return; } commitModal.modal('hide'); /* $.snackbar({ htmlAllowed: true, content: '  Saving ...' }) */ try { const url = `${window.gitlist.basepath}/${window.gitlist.repo}/git-helper/${window.gitlist.branch}/save` const response = await $.ajax({ url: url, type: 'POST', data: { value: value, email: inputs.email.val(), name: inputs.name.val(), comment: inputs.comment.val(), filename: filename } }) const json = JSON.parse(response) if (json.output !== '') { $.snackbar({ htmlAllowed: true, content: json.output, }) } if (json.error === true) { errorHandler(json); } else { originalCode = value; close(); $.snackbar({ htmlAllowed: true, content: '  The file is saved.', }) } } catch(e) { errorHandler(e); } }) const setScroll = () => { buttonFull.removeClass('active') buttonScroll.addClass('active') codeMirror.css('height', codeMirrorHeight) gitlist.viewer.setSize(null, codeMirrorHeight); if (!disableFull) { Cookies.set(cookieName, 'scroll', window.gitlist.cookieSettings) } } buttonScroll.click(setScroll) const setFull = () => { buttonScroll.removeClass('active') buttonFull.addClass('active') codeMirror.css('height', 'auto') gitlist.viewer.setSize(null, '100%'); Cookies.set(cookieName, 'full', window.gitlist.cookieSettings) } buttonFull.click(setFull) const cm = CodeMirror(function(elt) { pre.parentNode.replaceChild(elt, pre); }, { styleActiveLine: true, styleSelectedText: true, value: value, lineNumbers: true, matchBrackets: true, lineWrapping: true, readOnly: true, mode: mode, theme: window.gitlist.getActualThemeCodemirror(), }); gitlist.viewer = cm; const isReallyFull = currentSizing === 'full' && !disableFull; if (isReallyFull) { setFull() } else { setScroll() } const scrollToEditor = () => { const line = location.hash.startsWith('#L') ? location.hash.substring(2) : undefined if (line !== undefined) { setTimeout(() => { cm.scrollIntoView({line: line, char:0}, isReallyFull ? window.innerHeight / 2 : 100) }, 250) } } if (location.search.includes('edit=1')) { setTimeout(() => { buttonEdit.click(); scrollToEditor(); }, 500) } else { scrollToEditor(); } } createCodeMirror(); } }) public/js/gitgraph.js/000077500000000000000000000000001516067327100152005ustar00rootroot00000000000000public/js/gitgraph.js/LICENSE000066400000000000000000000027451516067327100162150ustar00rootroot00000000000000Copyright (c) 2011, Terrence Lee All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the fgdev nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.public/js/gitgraph.js/README.md000066400000000000000000000040201516067327100164530ustar00rootroot00000000000000gitgraph.js ======= gitgraph.js a tool for converting "git log --graph" from pure ascii characters graph to a canvas image. Quick Start (with PHP demo) ----- 1. Get a copy of this repo (clone or [download tarball](http://github.com/bluef/gitgraph.js/tarball/master)) 2. Put everything in the directory where PHP file can be excuted 3. Edit example.php, change the value of GIT_REPO_PATH on line 2 to the path of your repo define("GIT_REPO_PATH", "/path/to/your/repo"); 4. Go visit example.php in your browser Miscellaneous ------------ jQuery is only for parsing DOM License ------- Copyright (c) 2011, Terrence Lee All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the fgdev nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.public/js/gitgraph.js/gitgraph.css000066400000000000000000000011751516067327100175230ustar00rootroot00000000000000em {font-style:normal;} #git-graph-container, #rel-container {float:left;} #git-graph-container {} #git-graph-container li {list-style-type:none;height:20px;line-height:20px;overflow:hidden;} #git-graph-container li .node-relation {font-family:'Bitstream Vera Sans Mono', 'Courier', monospace;} #git-graph-container li .author {color:#666666;} #git-graph-container li .time {color:#999999;font-size:80%} #git-graph-container li a {color:#000000;} #git-graph-container li a em {color:#BB0000;border-bottom:1px dotted #BBBBBB;text-decoration:none;font-style:normal;} #rev-list {margin:0;padding:0 5px 0 0;} #graph-raw-list {margin:0px;}public/js/gitgraph.js/gitgraph.js000066400000000000000000000331611516067327100173470ustar00rootroot00000000000000/** * This File is a part of the GitList Project at https://github.com/patrikx3/gitlist * * @license https://github.com/patrikx3/gitlist/blob/master/LICENSE * @author Patrik Laszlo https://github.com/patrikx3/gitlist */ /* * Copyright (c) 2011, Terrence Lee * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ global.gitGraph = function (canvas, rawGraphList, config) { if (!canvas.getContext) { return; } if (typeof config === "undefined") { config = { unitSize: 20, lineWidth: 3, nodeRadius: 4 }; } var flows = []; var graphList = []; var ctx = canvas.getContext("2d"); var devicePixelRatio = window.devicePixelRatio || 1; var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; var ratio = devicePixelRatio / backingStoreRatio; var init = function () { var maxWidth = 0; var i; var l = rawGraphList.length; var row; var midStr; for (i = 0; i < l; i++) { midStr = rawGraphList[i].replace(/\s+/g, " ").replace(/^\s+|\s+$/g, ""); maxWidth = Math.max(midStr.replace(/(\_|\s)/g, "").length, maxWidth); row = midStr.split(""); graphList.unshift(row); } var width = maxWidth * config.unitSize; var height = graphList.length * config.unitSize; canvas.width = width * ratio; canvas.height = height * ratio; canvas.style.width = width + 'px'; canvas.style.height = height + 'px'; ctx.fillStyle = window.gitlist.canvasDotColor; ctx.lineWidth = config.lineWidth; ctx.lineJoin = "round"; ctx.lineCap = "round"; ctx.scale(ratio, ratio); }; var genRandomStr = function () { var chars = "0123456789ABCDEF"; var stringLength = 6; var randomString = '', rnum, i; for (i = 0; i < stringLength; i++) { rnum = Math.floor(Math.random() * chars.length); randomString += chars.substring(rnum, rnum + 1); } return randomString; }; var findFlow = function (id) { var i = flows.length; while (i-- && flows[i].id !== id) { } return i; }; var findColomn = function (symbol, row) { var i = row.length; while (i-- && row[i] !== symbol) { } return i; }; var findBranchOut = function (row) { if (!row) { return -1 } var i = row.length; while (i-- && !(row[i - 1] && row[i] === "/" && row[i - 1] === "|") && !(row[i - 2] && row[i] === "_" && row[i - 2] === "|")) { } return i; } var genNewFlow = function () { var newId; do { newId = genRandomStr(); } while (findFlow(newId) !== -1); return {id: newId, color: window.gitlist.randomCanvasLaneColors() }; }; //draw method var drawLineRight = function (x, y, color) { ctx.strokeStyle = color; ctx.beginPath(); ctx.moveTo(x, y + config.unitSize / 2); ctx.lineTo(x + config.unitSize, y + config.unitSize / 2); ctx.stroke(); }; var drawLineUp = function (x, y, color) { ctx.strokeStyle = color; ctx.beginPath(); ctx.moveTo(x, y + config.unitSize / 2); ctx.lineTo(x, y - config.unitSize / 2); ctx.stroke(); }; var drawNode = function (x, y, color) { ctx.strokeStyle = color; drawLineUp(x, y, color); ctx.beginPath(); ctx.arc(x, y, config.nodeRadius, 0, Math.PI * 2, true); ctx.fill(); }; var drawLineIn = function (x, y, color) { ctx.strokeStyle = color; ctx.beginPath(); ctx.moveTo(x + config.unitSize, y + config.unitSize / 2); ctx.lineTo(x, y - config.unitSize / 2); ctx.stroke(); }; var drawLineOut = function (x, y, color) { ctx.strokeStyle = color; ctx.beginPath(); ctx.moveTo(x, y + config.unitSize / 2); ctx.lineTo(x + config.unitSize, y - config.unitSize / 2); ctx.stroke(); }; var draw = function (graphList) { var colomn, colomnIndex, prevColomn, condenseIndex; var x, y; var color; var nodePos, outPos; var tempFlow; var prevRowLength = 0; var flowSwapPos = -1; var lastLinePos; var i, k, l; var condenseCurrentLength, condensePrevLength = 0, condenseNextLength = 0; var inlineIntersect = false; //initiate for first row for (i = 0, l = graphList[0].length; i < l; i++) { if (graphList[0][i] !== "_" && graphList[0][i] !== " ") { flows.push(genNewFlow()); } } y = (canvas.height / ratio) - config.unitSize * 0.5; //iterate for (i = 0, l = graphList.length; i < l; i++) { x = config.unitSize * 0.5; var currentRow = graphList[i]; var nextRow = graphList[i + 1]; var prevRow = graphList[i - 1]; flowSwapPos = -1; condenseCurrentLength = currentRow.filter(function (val) { return (val !== " " && val !== "_") }).length; if (nextRow) { condenseNextLength = nextRow.filter(function (val) { return (val !== " " && val !== "_") }).length; } else { condenseNextLength = 0; } //pre process begin //use last row for analysing if (prevRow) { if (!inlineIntersect) { //intersect might happen for (colomnIndex = 0; colomnIndex < prevRowLength; colomnIndex++) { if (prevRow[colomnIndex + 1] && (prevRow[colomnIndex] === "/" && prevRow[colomnIndex + 1] === "|") || ((prevRow[colomnIndex] === "_" && prevRow[colomnIndex + 1] === "|") && (prevRow[colomnIndex + 2] === "/"))) { flowSwapPos = colomnIndex; //swap two flow tempFlow = {id: flows[flowSwapPos].id, color: flows[flowSwapPos].color}; flows[flowSwapPos].id = flows[flowSwapPos + 1].id; flows[flowSwapPos].color = flows[flowSwapPos + 1].color; flows[flowSwapPos + 1].id = tempFlow.id; flows[flowSwapPos + 1].color = tempFlow.color; } } } if (condensePrevLength < condenseCurrentLength && ((nodePos = findColomn("*", currentRow)) !== -1 && (findColomn("_", currentRow) === -1))) { flows.splice(nodePos - 1, 0, genNewFlow()); } if (prevRowLength > currentRow.length && (nodePos = findColomn("*", prevRow)) !== -1) { if (findColomn("_", currentRow) === -1 && findColomn("/", currentRow) === -1 && findColomn("\\", currentRow) === -1) { flows.splice(nodePos + 1, 1); } } } //done with the previous row prevRowLength = currentRow.length; //store for next round colomnIndex = 0; //reset index condenseIndex = 0; condensePrevLength = 0; while (colomnIndex < currentRow.length) { colomn = currentRow[colomnIndex]; if (colomn !== " " && colomn !== "_") { ++condensePrevLength; } if (colomn === " " && currentRow[colomnIndex + 1] && currentRow[colomnIndex + 1] === "_" && currentRow[colomnIndex - 1] && currentRow[colomnIndex - 1] === "|") { currentRow.splice(colomnIndex, 1); currentRow[colomnIndex] = "/"; colomn = "/"; } //create new flow only when no intersetc happened if (flowSwapPos === -1 && colomn === "/" && currentRow[colomnIndex - 1] && currentRow[colomnIndex - 1] === "|") { flows.splice(condenseIndex, 0, genNewFlow()); } //change \ and / to | when it's in the last position of the whole row if (colomn === "/" || colomn === "\\") { if (!(colomn === "/" && findBranchOut(nextRow) === -1)) { if ((lastLinePos = Math.max(findColomn("|", currentRow), findColomn("*", currentRow))) !== -1 && (lastLinePos < colomnIndex - 1)) { while (currentRow[++lastLinePos] === " ") { } if (lastLinePos === colomnIndex) { currentRow[colomnIndex] = "|"; } } } } if (colomn === "*" && prevRow && prevRow[condenseIndex + 1] === "\\") { flows.splice(condenseIndex + 1, 1); } if (colomn !== " ") { ++condenseIndex; } ++colomnIndex; } condenseCurrentLength = currentRow.filter(function (val) { return (val !== " " && val !== "_") }).length; //do some clean up if (flows.length > condenseCurrentLength) { flows.splice(condenseCurrentLength, flows.length - condenseCurrentLength); } colomnIndex = 0; //a little inline analysis and draw process while (colomnIndex < currentRow.length) { colomn = currentRow[colomnIndex]; prevColomn = currentRow[colomnIndex - 1]; if (currentRow[colomnIndex] === " ") { currentRow.splice(colomnIndex, 1); x += config.unitSize; continue; } //inline interset if ((colomn === "_" || colomn === "/") && currentRow[colomnIndex - 1] === "|" && currentRow[colomnIndex - 2] === "_") { inlineIntersect = true; tempFlow = flows.splice(colomnIndex - 2, 1)[0]; flows.splice(colomnIndex - 1, 0, tempFlow); currentRow.splice(colomnIndex - 2, 1); colomnIndex = colomnIndex - 1; } else { inlineIntersect = false; } color = flows[colomnIndex].color; switch (colomn) { case "_" : drawLineRight(x, y, color); x += config.unitSize; break; case "*" : drawNode(x, y, color); break; case "|" : drawLineUp(x, y, color); break; case "/" : if (prevColomn && (prevColomn === "/" || prevColomn === " ")) { x -= config.unitSize; } drawLineOut(x, y, color); x += config.unitSize; break; case "\\" : drawLineIn(x, y, color); break; } ++colomnIndex; } y -= config.unitSize; } }; init(); draw(graphList); };public/js/global.js000077500000000000000000000133141516067327100145630ustar00rootroot00000000000000let $body; let $head; const Cookies = require('js-cookie') const scrollIntoViewOptions = { behavior: "instant", block: "start", inline: "start" } const navbarHeight = 80; const scrollIntoView = (el) => { el.scrollIntoView(scrollIntoViewOptions) if ((window.innerHeight + window.scrollY) <= document.body.offsetHeight - navbarHeight ) { window.scrollBy(0,-navbarHeight ) } } window.gitlist.scrollIntoView = scrollIntoView; /* const regExpEmail = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; window.gitlist.validate = { email: (email) => { return regExpEmail.test(String(email)); } } */ window.gitlist.getPaths = () => { const currentUrl = new URL(window.location) if (window.gitlist.basepath !== '') { currentUrl.pathname = currentUrl.pathname.substring(window.gitlist.basepath.length) } let paths = currentUrl.pathname.split('/'); return paths; } window.gitlist.clearInput = (name) => { const input = $(`[name=${name}]`) input.val('') Cookies.set(`p3x-gitlist-${name}`, '', window.gitlist.cookieSettings) input.focus() } window.gitlist.setInputQuery = (name) => { const input = $(`[name=${name}]`) Cookies.set(`p3x-gitlist-${name}`, input.val(), window.gitlist.cookieSettings) } window.gitlist.isDark =(theme = window.gitlist.getActualTheme()) => { for(let i = 0; i < window.gitlist.dark.length; i++ ) { if (window.gitlist.dark[i] === theme) { return true; } } return false; } window.gitlist.cookieSettings = { path: gitlist.basepath === '' ? '/' : gitlist.basepath, expires: 3650 } window.gitlist.getActualTheme = (theme = window.gitlist.getThemeCookie()) => { const actualTheme = theme.split('-')[1] return actualTheme; } window.gitlist.getActualThemeCodemirror = () => { if (window.gitlist.isDark(window.gitlist.getActualTheme())) { return window.gitlist.codemirrorTheme.dark; } else { return window.gitlist.codemirrorTheme.light; } } let currentTheme; let setTimeoutSwitch; window.gitlist.setTheme = () => { if ($body === undefined) { setTimeout(() => { window.gitlist.setTheme() }) return; } const theme = window.gitlist.getActualTheme(); // console.log('theming', 'currenTheme', currentTheme, 'new theme', theme); if (theme === currentTheme) { // console.log('same theme') return; } // console.log('p3x-gitlist switching theme') currentTheme = theme; if (window.gitlist.isDark(theme)) { $body.addClass('p3x-gitlist-dark') $body.removeClass('p3x-gitlist-light') if (gitlist.viewer !== undefined) { gitlist.viewer.setOption("theme", window.gitlist.codemirrorTheme.dark); } gitlist.diffEditors.forEach(editor => editor.setOption('theme', window.gitlist.codemirrorTheme.dark ) ) } else { $body.addClass('p3x-gitlist-light') $body.removeClass('p3x-gitlist-dark') if (gitlist.viewer !== undefined) { gitlist.viewer.setOption("theme", window.gitlist.codemirrorTheme.light); } gitlist.diffEditors.forEach(editor => editor.setOption('theme', window.gitlist.codemirrorTheme.light ) ) } window.gitlist.networkRedraw(); window.gitlist.treegraph(); // if (window.gitlist.lastloadSpan !== undefined && window.gitlist.lastloadSpan > 1000) { clearTimeout(setTimeoutSwitch) setTimeoutSwitch = setTimeout(() => { $('.p3x-gitlist-overlay').remove(); }, 250) // } } const pushHash = (hash) => { if(history.pushState) { const pushState = location.pathname + hash; history.pushState(null, null, pushState); } else { location.hash = hash; } } global.gitlist.scrollHash = function(element, event) { const url = new URL(element.href) const id = url.hash.substring(1) const elfind = document.getElementById(id + '-parent') if (elfind === null) { return true; } scrollIntoView(elfind); if (event !== undefined) { event.preventDefault() pushHash(url.hash) } return false; } $(function () { currentTheme = window.gitlist.getActualTheme(window.gitlist.loadTheme) $('.dropdown-toggle').dropdown(); $('[data-toggle="tooltip"]').tooltip() $body = $('body'); $head = $('head') // let waiter = 500; // let timeout = 500; Object.values(window.gitlist.themes).forEach(css => { // setTimeout(() => { $head.append(``) // }, timeout) // timeout += waiter; }) const es = document.getElementsByTagName('a') for(let i=0; i { Cookies.set(cookieName, input.val(), window.gitlist.cookieSettings) }) input.val(value); const listOptions = { valueNames: ['name', 'description'], indexAsync: true, }; const list = new List(id, listOptions); if (value !== undefined) { list.search(value); } inputClear.click(() => { Cookies.remove(cookieName); input.val(''); list.search('') }) } }) public/js/markdown.js000066400000000000000000000113001516067327100151330ustar00rootroot00000000000000const hljs = require('highlight.js/lib/highlight.js'); hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml.js')); hljs.registerLanguage('css', require('highlight.js/lib/languages/css.js')); hljs.registerLanguage('cmake', require('highlight.js/lib/languages/cmake.js')); hljs.registerLanguage('dockerfile', require('highlight.js/lib/languages/dockerfile.js')); hljs.registerLanguage('Dockerfile', require('highlight.js/lib/languages/dockerfile.js')); hljs.registerLanguage('less', require('highlight.js/lib/languages/less.js')); hljs.registerLanguage('scss', require('highlight.js/lib/languages/scss.js')); hljs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml.js')); hljs.registerLanguage('powershell', require('highlight.js/lib/languages/powershell.js')); hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript.js')); hljs.registerLanguage('js', require('highlight.js/lib/languages/javascript.js')); hljs.registerLanguage('json', require('highlight.js/lib/languages/json.js')); hljs.registerLanguage('bash', require('highlight.js/lib/languages/shell.js')); hljs.registerLanguage('php', require('highlight.js/lib/languages/php.js')); hljs.registerLanguage('shell', require('highlight.js/lib/languages/shell.js')); hljs.registerLanguage('typescript', require('highlight.js/lib/languages/typescript.js')); hljs.registerLanguage('ts', require('highlight.js/lib/languages/typescript.js')); $(function() { const markdownRenderer = new marked.Renderer(); const kebabCase = require('lodash/kebabCase') markdownRenderer.heading = function (text, level, raw) { level = level + 2; const ref = kebabCase(text).replace(/[^\x00-\xFF]/g, ""); const id = ref + '-parent'; const hover = ` onmouseenter="document.getElementById('${ref}').style.display = 'inline'" onmouseleave="document.getElementById('${ref}').style.display = 'none'" `; const element = `
${text} #
`; return element } markdownRenderer.link = function(href, title, text) { let a; if (href.startsWith('https:/') || href.startsWith('http:/')) { a = '' + text + ''; } else { const start = gitlist.basepath + '/' + gitlist.repo + '/blob/' + gitlist.branch + '/'; if (!location.pathname.startsWith(start)) { href = start + href; } a = '' + text + ''; } return a; } markdownRenderer.image = function(href, title, text) { title = title || ''; text = text || ''; let resultText = title; if (text !== '') { if (title !== '') { resultText += ' - '; } resultText += text; } const result = '' + htmlEncode(resultText) + ''; return result; }; markdownRenderer.code = (code, language ) => { if (language === undefined) { language = 'text'; } language = language.toLowerCase() if ((hljs.getLanguage(language) === 'undefined' || hljs.getLanguage(language) === undefined) && language !== 'text') { console.error(`Please add highlight.js as a language (could be a marked error as well, sometimes it thinks a language): ${language} We are not loading everything, since it is about 500kb`) } language = language === 'text' || language === undefined ? 'html' : language; const validLang = !!(language && hljs.getLanguage(language)); const highlighted = validLang ? hljs.highlight(language, code).value : code; return `
${highlighted}
`; }; markdownRenderer.codespan = (code) => { const lang = 'html'; const highlighted = hljs.highlight(lang, code).value ; return `${highlighted}`; } const mdContent = $('#p3x-gitlist-readme'); if (mdContent.length) { const html = marked(mdContent.text(), { renderer: markdownRenderer }); mdContent.html(twemoji.parse(html, { folder: 'svg', ext: '.svg', })); } }); public/js/menu-responsive.js000066400000000000000000000015721516067327100164620ustar00rootroot00000000000000module.exports = (options) => { const { menuList } = options; let { nav, navButton } = options if (nav === undefined) { nav = $('#p3x-gitlist-navigation') } if (navButton === undefined) { navButton = $('#p3x-gitlist-navigation-menu-button'); } const debounce = require('lodash/debounce') const debounceResize = debounce(() => { if (navButton.is(':visible')) { menuList.css({ 'maxHeight': 'auto', 'overflowX': 'visible', }); } else { const allowedMaxHeight = window.innerHeight - nav.height() - 20; menuList.css({ 'maxHeight': allowedMaxHeight, 'overflowX': 'auto' }); } }, 250); window.addEventListener('resize', debounceResize); debounceResize(); return debounceResize; }public/js/network.js000066400000000000000000000445121516067327100150150ustar00rootroot00000000000000/** * Network Graph JS * This File is a part of the GitList Project at https://github.com/patrikx3/gitlist * * @license https://github.com/patrikx3/gitlist/blob/master/LICENSE * @author Lukas Domnick http://github.com/lukx * @author Patrik Laszlo https://github.com/patrikx3/gitlist */ // global config const cfg = { get laneColors() { if (window.gitlist.isDark()) { return ['#BDBDBD', '#BBDEFB', '#03A9F4', '#2196F3', '#BDBDBD', '#FFFFFF']; } else { return ['#455A64', '#607D8B', '#757575', '#9E9E9E', '#CFD8DC', '#BDBDBD']; } }, get dotColor() { if (window.gitlist.isDark()) { return '#ffffff88'; } else { return '#00000088'; } }, laneHeight: 20, columnWidth: 42, dotRadius: 3 }; Object.defineProperty(window.gitlist, 'canvasLaneColors', { get: () => { return cfg.laneColors; } }) Object.defineProperty(window.gitlist, 'canvasDotColor', { get: () => { return cfg.dotColor; } }) window.gitlist.randomCanvasLaneColors = () => { const items = window.gitlist.canvasLaneColors; return items[Math.floor(Math.random() * items.length)]; } const $ = require('jquery') const phpDate = require('php-date') /** * DragScrollr is a custom made x/y-Drag Scroll Plugin for Gitlist * * TODO: Make this touch-scrollable */ $.fn.dragScrollr = function () { let lastX, lastY, hotZone = 200, container = this.first(), domElement = container[0]; // so basically container without the jQuery stuff function handleMouseDown(evt) { container.on('mousemove', handleMouseMove); container.on('mouseup', handleMouseUp); container.on('mouseleave', handleMouseUp); lastX = evt.pageX; lastY = evt.pageY; } function handleMouseMove(evt) { evt.preventDefault(); // save the last scroll position to figure out whether the scroll event has entered the hot zone const lastScrollLeft = domElement.scrollLeft; domElement.scrollLeft = domElement.scrollLeft + lastX - evt.pageX; domElement.scrollTop = domElement.scrollTop + lastY - evt.pageY; if (lastScrollLeft > hotZone && domElement.scrollLeft <= hotZone) { container.trigger('enterHotZone'); } // when we move into the hot zone lastX = evt.pageX; lastY = evt.pageY; } function handleMouseUp(evt) { container.off('mousemove', handleMouseMove) .off('mouseup', handleMouseUp) .off('mouseleave', handleMouseUp); } // now bind the initial event container.on('mousedown', handleMouseDown); // return this instead of container, because of the .first() we applied - remember? return this; }; function graphLaneManager() { const that = {}, occupiedLanes = []; // "private" methods function findLaneNumberFor(commit) { if (commit.lane) { // oh? we've already got a lane? return commit.lane.number; } // find out which lane may draw our dot on. Start with a free one let laneNumber = findFreeLane(); // if the child is a merge, we need to figure out which lane we may render this commit on. // Rules are simple: A "parent" by the same author as the merge may render on the same line as the child // others take the next free lane. // furthermore, commits in a linear line of events may stay on the same lane, too if (commit.children.length > 0) { if (!commit.children[0].isMerge // linear ... || (commit.children[0].isMerge && commit.children[0].author.email === commit.author.email) // same author ) { laneNumber = commit.children[0].lane.number; } } return laneNumber; } function findFreeLane() { let i = 0; while (true) { // if an array index is not yet defined or set to false, the lane with that number is free. if (!occupiedLanes[i]) { return i; } i++; } } that.occupy = function (lane) { // make sure we work with lane numbers here if (typeof lane === 'object') { lane = lane.number; } occupiedLanes[lane] = true; }; that.free = function (lane) { // make sure we work with lane numbers here if (typeof lane === 'object') { lane = lane.number; } occupiedLanes[lane] = false; }; that.getLaneForCommit = function (commit) { // does this commit have a lane already? if (commit.lane) return commit.lane; const laneNumber = findLaneNumberFor(commit); return that.getLane(laneNumber); }; that.getLane = function (laneNumber) { return { 'number': laneNumber, 'centerY': (laneNumber * cfg.laneHeight) + (cfg.laneHeight / 2), 'color': cfg.laneColors[laneNumber % cfg.laneColors.length] }; }; return that; } function commitDetailOverlay() { var that = {}, el = $('
'), imageDisplay = $('').appendTo(el), messageDisplay = $('
').appendTo(el), metaDisplay = $('
').appendTo(el), authorDisplay = $('').appendTo(metaDisplay), dateDisplay = $('').appendTo(metaDisplay); el.hide(); /** * Pads an input number with one leading '0' if needed, and assure it's a string * * @param input Number * @returns String */ function twoDigits(input) { if (input < 10) { return '0' + input; } return '' + input; } /** * Transform a JS Native Date Object to a string, maintaining the same format given in the commit_list view * 'd/m/Y \\a\\t H:i:s' * * @param date Date * @returns String */ function getDateString(date) { return phpDate(gitlist.dateFormat, date) } /** * update the author view * * @param author */ function setAuthor(author) { authorDisplay.html(author.name) .attr('href', 'mailto:' + author.email); imageDisplay.attr('src', author.image); } /** * Set the commit that is being displayed in this detail overlay instance * * @param commit * @return that */ that.setCommit = function (commit) { setAuthor(commit.author); dateDisplay.html(' authored on ' + getDateString(commit.date)); messageDisplay.html(commit.message); return that; }; // expose some jquery functions that.show = function () { el.show(); return that; }; that.hide = function () { el.hide(); return that; }; that.appendTo = function (where) { el.appendTo(where); return that; }; that.positionTo = function (x, y) { el.css('left', x + 'px'); el.css('top', y + 'px'); }; that.outerWidth = function () { return el.outerWidth.apply(el, arguments); }; return that; } function commitDataRetriever(startPage, callback) { let that = {}, nextPage = startPage; let indicatorElements; global.isLoading = false; that.updateIndicators = function () { if (global.isLoading) { $(indicatorElements).addClass('loading-commits'); } else { $(indicatorElements).removeClass('loading-commits'); } }; that.bindIndicator = function (el) { if (!indicatorElements) { indicatorElements = $(el); } else { indicatorElements = indicatorElements.add(el); } }; that.unbindIndicator = function (el) { indicatorElements.not(el); }; function handleNetworkDataLoaded(data) { global.isLoading = false; that.updateIndicators(); nextPage = data.nextPage; if (!data.commits || data.commits.length === 0) { callback(null); } callback(data.commits); } function handleNetworkDataError() { throw "Network Data Error while retrieving Commits"; } that.retrieve = function () { if (!nextPage) { callback(null); return; } global.isLoading = true; that.updateIndicators(); $.ajax({ dataType: "json", url: nextPage, success: handleNetworkDataLoaded, error: handleNetworkDataError }); }; that.hasMore = function () { return (!!nextPage); }; return that; } window.gitlist.networkRedraw = () => { // initialise network graph only when there is one network graph container on the page if ($('div.network-graph').length !== 1) { return; } // the element into which we will render our graph let commitsGraph = $('div.network-graph').first(); commitsGraph.find('svg').remove(); commitsGraph.find('.network-commit-overlay').remove(); let laneManager = graphLaneManager() let dataRetriever = commitDataRetriever(commitsGraph.data('source'), handleCommitsRetrieved) let paper = Raphael(commitsGraph[0], commitsGraph.width(), commitsGraph.height()) let usedColumns = 0 let detailOverlay = commitDetailOverlay() dataRetriever.bindIndicator(commitsGraph.parent('.network-view')); detailOverlay.appendTo(commitsGraph); function handleEnterHotZone() { dataRetriever.retrieve(); } function handleCommitsRetrieved(commits) { // no commits or empty commits array? Well, we can't draw a graph of that if (commits === null) { handleNoAvailableData(); return; } prepareCommits(commits); renderCommits(commits); } function handleNoAvailableData() { window.console && console.log('No (more) Data available'); } const awaitedParents = {}; function prepareCommits(commits) { $.each(commits, function (index, commit) { prepareCommit(commit); }); } function prepareCommit(commit) { // make "date" an actual JS Date object commit.date = new Date(commit.date * 1000); // the parents will be filled once they have become prepared commit.parents = []; // we will want to store this commit's children commit.children = getChildrenFor(commit); commit.isFork = (commit.children.length > 1); commit.isMerge = (commit.parentsHash.length > 1); // after a fork, the occupied lanes must be cleaned up. The children used some lanes we no longer occupy if (commit.isFork === true) { $.each(commit.children, function (key, thisChild) { // free this lane laneManager.occupy(thisChild.lane); }); } commit.lane = laneManager.getLaneForCommit(commit); // now the lane we chose must be marked occupied again. laneManager.occupy(commit.lane); registerAwaitedParentsFor(commit); } /** * Add a new childCommit to the dictionary of awaited parents * * @param commit who is waiting? */ function registerAwaitedParentsFor(commit) { // This commit's parents are not yet known in our little world, as we are rendering following the time line. // Therefore we are registering this commit as "waiting" for each of the parent hashes $.each(commit.parentsHash, function (key, thisParentHash) { // If awaitedParents does not already have a key for thisParent's hash, initialise as array if (!awaitedParents.hasOwnProperty(thisParentHash)) { awaitedParents[thisParentHash] = [commit]; } else { awaitedParents[thisParentHash].push(commit); } }); } function getChildrenFor(commit) { let children = []; if (awaitedParents.hasOwnProperty(commit.hash)) { // there are child commits waiting children = awaitedParents[commit.hash]; // let the children know their parent objects $.each(children, function (key, thisChild) { thisChild.parents.push(commit); }); // remove this item from parentsBeingWaitedFor delete awaitedParents[commit.hash]; } return children; } const lastRenderedDate = new Date(0); function renderCommits(commits) { let neededWidth = ((usedColumns + Object.keys(commits).length) * cfg.columnWidth); if (neededWidth > paper.width) { extendPaper(neededWidth, paper.height); } else if (dataRetriever.hasMore()) { // this is the case when we have not loaded enough commits to fill the paper yet. Get some more then... dataRetriever.retrieve(); } $.each(commits, function (index, commit) { if (lastRenderedDate.getYear() !== commit.date.getYear() || lastRenderedDate.getMonth() !== commit.date.getMonth() || lastRenderedDate.getDate() !== commit.date.getDate()) { // TODO: If desired, one could add a time scale on top, maybe. } renderCommit(commit); }); } function renderCommit(commit) { // find the column this dot is drawn on usedColumns++; commit.column = usedColumns; commit.dot = paper.circle(getXPositionForColumnNumber(commit.column), commit.lane.centerY, cfg.dotRadius); commit.dot.attr({ fill: commit.lane.color, stroke: 'none', cursor: 'pointer' }) .data('commit', commit) .mouseover(handleCommitMouseover) .mouseout(handleCommitMouseout) .click(handleCommitClick); // maybe we have not enough space for the lane yet if (commit.lane.centerY + cfg.laneHeight > paper.height) { extendPaper(paper.width, commit.lane.centerY + cfg.laneHeight) } $.each(commit.children, function (idx, thisChild) { // if there is one child only, stay on the commit's lane as long as possible when connecting the dots. // but if there is more than one child, switch to the child's lane ASAP. // this is to display merges and forks where they happen (ie. at a commit node/ a dot), rather than // connecting from a line. // So: commit.isFork decides whether or not we must switch lanes early connectDots(commit, thisChild, commit.isFork); }); } /** * * @param firstCommit * @param secondCommit * @param switchLanesEarly (boolean): Move the line to the secondCommit's lane ASAP? Defaults to false */ function connectDots(firstCommit, secondCommit, switchLanesEarly) { // default value for switchLanesEarly switchLanesEarly = switchLanesEarly || false; const lineLane = switchLanesEarly ? secondCommit.lane : firstCommit.lane; // the connection has 4 stops, resulting in the following 3 segments: // - from the x/y center of firstCommit.dot to the rightmost end (x) of the commit's column, with y=lineLane // - from the rightmost end of firstCommit's column, to the leftmost end of secondCommit's column // - from the leftmost end of secondCommit's column (y=lineLane) to the x/y center of secondCommit paper.path( getSvgLineString( [firstCommit.dot.attr('cx'), firstCommit.dot.attr('cy')], [firstCommit.dot.attr('cx') + (cfg.columnWidth / 2), lineLane.centerY], [secondCommit.dot.attr('cx') - (cfg.columnWidth / 2), lineLane.centerY], [secondCommit.dot.attr('cx'), secondCommit.dot.attr('cy')] ) ).attr({"stroke": lineLane.color, "stroke-width": 2}).toBack(); } // set together a path string from any amount of arguments // each argument is an array of [x, y] within the paper's coordinate system function getSvgLineString() { if (arguments.length < 2) return; let svgString = 'M' + arguments[0][0] + ' ' + arguments[0][1]; for (let i = 1, j = arguments.length; i < j; i++) { svgString += 'L' + arguments[i][0] + ' ' + arguments[i][1]; } return svgString; } function handleCommitMouseover(evt) { detailOverlay.setCommit(this.data('commit')) .show(); let xPos = evt.pageX - commitsGraph.offset().left + commitsGraph.scrollLeft() - (detailOverlay.outerWidth() / 2); // check that x doesn't run out the viewport xPos = Math.max(xPos, commitsGraph.scrollLeft() + 10); xPos = Math.min(xPos, commitsGraph.scrollLeft() + commitsGraph.width() - detailOverlay.outerWidth() - 10); detailOverlay.positionTo(xPos, evt.pageY - commitsGraph.offset().top + commitsGraph.scrollTop() + 10); } function handleCommitMouseout(evt) { detailOverlay.hide(); } function handleCommitClick(evt) { location.href = this.data('commit').details; } function getXPositionForColumnNumber(columnNumber) { // we want the column's center point return (paper.width - (columnNumber * cfg.columnWidth) + (cfg.columnWidth / 2)); } function extendPaper(newWidth, newHeight) { const deltaX = newWidth - paper.width; paper.setSize(newWidth, newHeight); // fixup parent's scroll position try { paper.canvas.parentNode.scrollLeft = paper.canvas.parentNode.scrollLeft + deltaX; } catch (e) { console.warn(e) } // now fixup the x positions of existing circles and lines paper.forEach(function (el) { if (el.type === "circle") { el.attr('cx', el.attr('cx') + deltaX); } else if (el.type === "path") { let newXTranslation = el.data('currentXTranslation') || 0; newXTranslation += deltaX; el.transform('t' + newXTranslation + ' 0'); el.data('currentXTranslation', newXTranslation); } }); } commitsGraph.dragScrollr(); commitsGraph.on('enterHotZone', handleEnterHotZone); // load initial data dataRetriever.retrieve(); } public/js/paginate.js000066400000000000000000000026471516067327100151170ustar00rootroot00000000000000$(function() { let $pager; let loading = false; let button; let noMore = false; const nextCommitListItem = () => { if (loading === true) { return; } loading = true; const href = button.attr('href'); //console.log(href); if (href === undefined) { loading = false; if (!noMore) { $.snackbar({ htmlAllowed: true, content: `There are no more commits.` }); noMore = true; } return } noMore = false; const retrieve = `${location.pathname}${href}` $.ajax({ url: retrieve, async: true, type: "GET", }).then(function(html) { $pager.after(html); $pager.remove(); loading = false; paginate(); }); } function paginate() { $pager = $('.pager'); button = $pager.find('.next a'); button.one('click', function (e) { e.preventDefault(); nextCommitListItem() return false; }); } paginate(); if (button.length > 0) { $(window).scroll(function () { if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) { nextCommitListItem(); } }); } }) public/js/theme-switcher.js000066400000000000000000000053471516067327100162570ustar00rootroot00000000000000const themes = require('./themes.js') window.gitlist.themes = themes; const Cookies = require('js-cookie') const themeCookieName = 'gitlist-bootstrap-theme' function getThemeCookie() { const theme = Cookies.get(themeCookieName) return theme || 'bootstrap-cosmo'; } gitlist.getThemeCookie = getThemeCookie; $(function () { const themeList = $('#theme-list'); const menuResponsive = require('./menu-responsive') const debounceResize = menuResponsive({ menuList: themeList, }) function setThemeCookie(theme) { Cookies.set(themeCookieName, theme, window.gitlist.cookieSettings); } const currentCookie = getThemeCookie('gitlist-bootstrap-theme'); const darkMenu = []; const lightMenu = [] for (let key in themes) { const actualTheme = key.substring(10) const menu = '
  • ' + actualTheme + '
  • '; if (window.gitlist.isDark(actualTheme)) { darkMenu.push(menu) } else { lightMenu.push(menu) } } for (let menu of lightMenu) { themeList.append(menu); } themeList.append('
  • ') for (let menu of darkMenu) { themeList.append(menu); } const themesheet = $('#bootstrap-theme'); let deferredSwitchTheme; $('.theme-link').click(function (event) { event.preventDefault(); const generateNewTheme = () => { debounceResize(); themeList.find('.active').removeClass('active'); const $this = $(this); $this.parent().addClass('active'); const themeurl = themes[$this.attr('data-theme')]; setThemeCookie($this.attr('data-theme')); const href = themeurl; const currentHref = themesheet.attr('href') // console.log('currentHref', currentHref, 'href', href) if (currentHref === href) { return; } // console.log('p3x-gitlist themer swtich') themesheet.attr('href', href); gitlist.setTheme() } clearTimeout(deferredSwitchTheme) deferredSwitchTheme = setTimeout(() => { $('body').prepend(`

    Hang on, we are not reloading the server ...
    `) clearTimeout(deferredSwitchTheme) deferredSwitchTheme = setTimeout(() => { generateNewTheme() }, 250) }, 250); }); }); public/js/themes.js000077500000000000000000000044531516067327100146140ustar00rootroot00000000000000 const themes = { "bootstrap-default": "generated/css/bootstrap-default.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-solar": "generated/css/bootstrap-solar.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-cerulean": "generated/css/bootstrap-cerulean.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-cosmo": "generated/css/bootstrap-cosmo.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-cyborg": "generated/css/bootstrap-cyborg.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-darkly": "generated/css/bootstrap-darkly.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-flatly": "generated/css/bootstrap-flatly.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-journal": "generated/css/bootstrap-journal.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-lumen": "generated/css/bootstrap-lumen.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-paper": "generated/css/bootstrap-paper.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-readable": "generated/css/bootstrap-readable.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-sandstone": "generated/css/bootstrap-sandstone.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-simplex": "generated/css/bootstrap-simplex.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-slate": "generated/css/bootstrap-slate.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-spacelab": "generated/css/bootstrap-spacelab.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-superhero": "generated/css/bootstrap-superhero.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-united": "generated/css/bootstrap-united.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css", "bootstrap-yeti": "generated/css/bootstrap-yeti.70d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380.css" }; module.exports = themes; public/js/treegraph.js000066400000000000000000000006351516067327100153030ustar00rootroot00000000000000window.gitlist.treegraph = () => { if (!document.getElementById('graph-canvas')) { return; } const log = $("#p3x-gitlist-treegraph-log"); if (log) { const graphList = []; $("#graph-raw-list li span.node-relation").each(function () { graphList.push($(this).text()); }) global.gitGraph(document.getElementById('graph-canvas'), graphList); } } public/less/000077500000000000000000000000001516067327100133125ustar00rootroot00000000000000public/less/browser.less000066400000000000000000000015661516067327100156750ustar00rootroot00000000000000#p3x-gitlist-branch-list { overflow: hidden; white-space:nowrap; text-overflow:ellipsis; max-width:200px; display:inline-block; @media only screen and (max-width : 768px) { max-width: 100%; width: 100%; } } .p3x-gitlist-branch-menu-header, .p3x-gitlist-branch-menu-item { padding: @padding-base-vertical; } #p3x-gitlist-branch-list-container { .p3x-gitlist-branch-menu-item, a { text-decoration: none; color: @dropdown-link-color; } .p3x-gitlist-branch-menu-item:hover { cursor: pointer; } .p3x-gitlist-branch-menu-item:hover, .p3x-gitlist-branch-menu-item:hover a { background-color: @dropdown-link-hover-bg; color: @dropdown-link-hover-color; } .p3x-gitlist-branch-menu-item.active, .p3x-gitlist-branch-menu-item.active a { background-color: @dropdown-link-active-bg; color: @dropdown-link-active-color; } } public/less/clone-button.less000066400000000000000000000000741516067327100166140ustar00rootroot00000000000000#p3x-gitlist-modal-clone { input { color: black; } }public/less/codemirror.less000066400000000000000000000002611516067327100163460ustar00rootroot00000000000000 .p3x-gitlist-light { .CodeMirror { border: 1px solid @gray-lighter; } } .p3x-gitlist-dark { .CodeMirror { border: 1px solid @navbar-default-bg !important; } } public/less/default.less000066400000000000000000000036411516067327100156320ustar00rootroot00000000000000@import "../../node_modules/snackbarjs/src/snackbar"; @import "../../node_modules/snackbarjs/themes-less/material"; #snackbar-container { left: auto !important; right: 20px !important; } @media (max-width: 767px) { #snackbar-container { left: 0px !important; right: 0px !important; width: 100%; .snackbar { min-width: 100%; } [class="snackbar snackbar-opened"] ~ .snackbar.toast { margin-top: 20px; } [class="snackbar snackbar-opened"] { border-radius: 0; margin-bottom: 0; } } } .p3x-gitlist-button { .btn { margin-bottom: @padding-base-vertical !important; } } .p3x-gitlist-light { .CodeMirror { border: 1px solid @gray-lighter; } } .p3x-gitlist-dark { .CodeMirror { border: 1px solid @navbar-default-bg !important; } } .p3x-gitlist-dark { #snackbar-container > div { border: 1px solid @navbar-default-border; } code { overflow-x: auto; white-space:pre-wrap; } code.p3x-gitlist-code { background-color: lighten(@navbar-inverse-bg, 5%); color: @navbar-inverse-color; border-color: @navbar-inverse-border; } } .p3x-gitlist-markdown-heading-container { position: relative; } a.p3x-gitlist-markdown-heading-link { display: none; font-size: inherit; text-decoration: none !important; } .p3x-gitlist-markdown-image { max-width: 100%; } .p3x-gitlist-breadcrumb-divider { min-height: @padding-base-vertical; display: block; clear: both;; } img.emoji { height: 1em; width: 1em; margin: 0 .05em 0 .1em; vertical-align: -0.1em; } .p3x-list-item-header { font-weight: bold !important; } .breadcrumb { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } @import "index"; @import "clone-button.less"; @import "footer"; @import "main-tabs"; @import "treegraph"; @import "file"; @import "markdown"; @import "browser"; @import "overlay"; @import "search"; @import "codemirror";public/less/file.less000066400000000000000000000001461516067327100151220ustar00rootroot00000000000000#p3x-gitlist-file-codemirror-exceeded { display: none; margin-bottom: @padding-base-horizontal; } public/less/footer.less000066400000000000000000000002521516067327100154770ustar00rootroot00000000000000 #p3x-gitlist-footer { margin-top: @padding-base-vertical; text-align: right; } .p3x-gitlist-header-height { height: @navbar-height + (@navbar-height * 0.5); } public/less/index.less000066400000000000000000000001061516067327100153060ustar00rootroot00000000000000#p3x-gitlist-index { a { text-decoration: none !important; } }public/less/main-tabs.less000066400000000000000000000000621516067327100160530ustar00rootroot00000000000000#p3x-gitlist-main-tabs * { margin-bottom: 2px; }public/less/markdown.less000066400000000000000000000003641516067327100160270ustar00rootroot00000000000000.p3x-gitlist-light { @import (less) '../../node_modules/highlight.js/styles/github.css'; } .p3x-gitlist-dark { @import (less) '../../node_modules/highlight.js/styles/dracula.css'; } #p3x-gitlist-readme { pre { padding: 0; } } public/less/overlay.less000066400000000000000000000006271516067327100156700ustar00rootroot00000000000000.p3x-gitlist-overlay { i { font-size: 400% !important; } z-index: 999999; font-size: 125%; position: fixed; left: 0; top: 0; width: 100vw; height: 100vh; text-align:center; /*Flexbox*/ display: flex; flex-direction: column; align-items: center; align-content: center; justify-content: center; background-color: rgba(0, 0, 0, 0.9); color: rgba(255, 255, 255, 0.5); } public/less/search.less000066400000000000000000000001721516067327100154470ustar00rootroot00000000000000.p3x-gitlist-search-match { overflow-x: auto; white-space: pre; margin: 0; padding-bottom: 0; padding-top: 0; } public/less/style.less000066400000000000000000000001341516067327100153400ustar00rootroot00000000000000// Init Bootstrap @import "../../node_modules/bootstrap/less/variables"; @import "default"; public/less/theme/000077500000000000000000000000001516067327100144145ustar00rootroot00000000000000public/less/theme/cerulean.less000066400000000000000000000003201516067327100170750ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/cerulean/variables"; @import "../../../node_modules/bootswatch/cerulean/bootswatch"; @import "../default"; public/less/theme/cosmo.less000066400000000000000000000003121516067327100164200ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/cosmo/variables"; @import "../../../node_modules/bootswatch/cosmo/bootswatch"; @import "../default"; public/less/theme/cyborg.less000066400000000000000000000003141516067327100165670ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/cyborg/variables"; @import "../../../node_modules/bootswatch/cyborg/bootswatch"; @import "../default"; public/less/theme/darkly.less000066400000000000000000000003141516067327100165700ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/darkly/variables"; @import "../../../node_modules/bootswatch/darkly/bootswatch"; @import "../default"; public/less/theme/default.less000066400000000000000000000001211516067327100167220ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../default"; public/less/theme/flatly.less000066400000000000000000000003141516067327100165750ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/flatly/variables"; @import "../../../node_modules/bootswatch/flatly/bootswatch"; @import "../default"; public/less/theme/journal.less000066400000000000000000000003161516067327100167560ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/journal/variables"; @import "../../../node_modules/bootswatch/journal/bootswatch"; @import "../default"; public/less/theme/lumen.less000066400000000000000000000003121516067327100164200ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/lumen/variables"; @import "../../../node_modules/bootswatch/lumen/bootswatch"; @import "../default"; public/less/theme/paper.less000066400000000000000000000003121516067327100164070ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/paper/variables"; @import "../../../node_modules/bootswatch/paper/bootswatch"; @import "../default"; public/less/theme/readable.less000066400000000000000000000003201516067327100170360ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/readable/variables"; @import "../../../node_modules/bootswatch/readable/bootswatch"; @import "../default"; public/less/theme/sandstone.less000066400000000000000000000003221516067327100172770ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/sandstone/variables"; @import "../../../node_modules/bootswatch/sandstone/bootswatch"; @import "../default"; public/less/theme/simplex.less000066400000000000000000000003161516067327100167650ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/simplex/variables"; @import "../../../node_modules/bootswatch/simplex/bootswatch"; @import "../default"; public/less/theme/slate.less000066400000000000000000000003121516067327100164100ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "../../../node_modules/bootswatch/slate/variables"; @import "../../../node_modules/bootswatch/slate/bootswatch"; @import "../default"; public/less/theme/solar.less000066400000000000000000000002101516067327100164150ustar00rootroot00000000000000 @import "../../../node_modules/bootstrap/less/bootstrap"; @import "solar/variables"; @import "solar/bootswatch"; @import "../default"; public/less/theme/solar/000077500000000000000000000000001516067327100155345ustar00rootroot00000000000000public/less/theme/solar/bootswatch.less000066400000000000000000000050261516067327100206040ustar00rootroot00000000000000// Solar 3.3.7 // Bootswatch // ----------------------------------------------------- @web-font-path: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700"; .web-font(@path) { @import url("@{path}"); } .web-font(@web-font-path); // Navbar ===================================================================== // Buttons ==================================================================== // Typography ================================================================= .text-primary, .text-primary:hover { color: @brand-primary; } .text-success, .text-success:hover { color: @brand-success; } .text-danger, .text-danger:hover { color: @brand-danger; } .text-warning, .text-warning:hover { color: @brand-warning; } .text-info, .text-info:hover { color: @brand-info; } .bg-success, .bg-info, .bg-warning, .bg-danger { color: #fff; } // Tables ===================================================================== table, .table { .success, .info, .warning, .danger { td, th { color: #fff; } } } // Forms ====================================================================== .has-warning { .help-block, .control-label, .radio, .checkbox, .radio-inline, .checkbox-inline, &.radio label, &.checkbox label, &.radio-inline label, &.checkbox-inline label, .form-control-feedback { color: @brand-warning; } .form-control, .form-control:focus, .input-group-addon { border-color: @brand-warning; } } .has-error { .help-block, .control-label, .radio, .checkbox, .radio-inline, .checkbox-inline, &.radio label, &.checkbox label, &.radio-inline label, &.checkbox-inline label, .form-control-feedback { color: @brand-danger; } .form-control, .form-control:focus, .input-group-addon { border-color: @brand-danger; } } .has-success { .help-block, .control-label, .radio, .checkbox, .radio-inline, .checkbox-inline, &.radio label, &.checkbox label, &.radio-inline label, &.checkbox-inline label, .form-control-feedback { color: @brand-success; } .form-control, .form-control:focus, .input-group-addon { border-color: @brand-success; } } .input-group-addon { color: @text-color; } // Navs ======================================================================= // Indicators ================================================================= // Progress bars ============================================================== // Containers =================================================================public/less/theme/solar/variables.less000066400000000000000000000661751516067327100204130ustar00rootroot00000000000000// Solar 3.3.7 // Variables // -------------------------------------------------- //== Colors // //## Gray and brand colors for use across Bootstrap. @gray-base: #000; @gray-darker: #002B36; @gray-dark: #073642; @gray: #839496; @gray-light: #EEE8D5; @gray-lighter: #FDF6E3; @brand-primary: #B58900; @brand-success: #2AA198; @brand-info: #268BD2; @brand-warning: #CB4B16; @brand-danger: #D33682; //== Scaffolding // //## Settings for some of the most global styles. //** Background color for ``. @body-bg: @gray-darker; //** Global text color on ``. @text-color: @gray; //** Global textual link color. @link-color: @brand-success; //** Link hover color set via `darken()` function. @link-hover-color: @link-color; //** Link hover decoration. @link-hover-decoration: underline; //== Typography // //## Font, line-height, and color for body text, headings, and more. @font-family-sans-serif: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; @font-family-serif: Georgia, "Times New Roman", Times, serif; //** Default monospace fonts for ``, ``, and `
    `.
    @font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
    @font-family-base:        @font-family-sans-serif;
    
    @font-size-base:          14px;
    @font-size-large:         ceil((@font-size-base * 1.25)); // ~18px
    @font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
    
    @font-size-h1:            floor((@font-size-base * 2.6)); // ~36px
    @font-size-h2:            floor((@font-size-base * 2.15)); // ~30px
    @font-size-h3:            ceil((@font-size-base * 1.7)); // ~24px
    @font-size-h4:            ceil((@font-size-base * 1.25)); // ~18px
    @font-size-h5:            @font-size-base;
    @font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px
    
    //** Unit-less `line-height` for use in components like buttons.
    @line-height-base:        1.428571429; // 20/14
    //** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
    @line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px
    
    //** By default, this inherits from the ``.
    @headings-font-family:    inherit;
    @headings-font-weight:    500;
    @headings-line-height:    1.1;
    @headings-color:          inherit;
    
    
    //== Iconography
    //
    //## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
    
    //** Load fonts from this directory.
    @icon-font-path:          "../fonts/";
    //** File name for all font files.
    @icon-font-name:          "glyphicons-halflings-regular";
    //** Element ID within SVG icon file.
    @icon-font-svg-id:        "glyphicons_halflingsregular";
    
    
    //== Components
    //
    //## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
    
    @padding-base-vertical:     6px;
    @padding-base-horizontal:   12px;
    
    @padding-large-vertical:    10px;
    @padding-large-horizontal:  16px;
    
    @padding-small-vertical:    5px;
    @padding-small-horizontal:  10px;
    
    @padding-xs-vertical:       1px;
    @padding-xs-horizontal:     5px;
    
    @line-height-large:         1.3333333; // extra decimals for Win 8.1 Chrome
    @line-height-small:         1.5;
    
    @border-radius-base:        4px;
    @border-radius-large:       6px;
    @border-radius-small:       3px;
    
    //** Global color for active items (e.g., navs or dropdowns).
    @component-active-color:    #fff;
    //** Global background color for active items (e.g., navs or dropdowns).
    @component-active-bg:       @gray-dark;
    
    //** Width of the `border` for generating carets that indicate dropdowns.
    @caret-width-base:          4px;
    //** Carets increase slightly in size for larger components.
    @caret-width-large:         5px;
    
    
    //== Tables
    //
    //## Customizes the `.table` component with basic values, each used across all table variations.
    
    //** Padding for ``s and ``s.
    @table-cell-padding:            8px;
    //** Padding for cells in `.table-condensed`.
    @table-condensed-cell-padding:  5px;
    
    //** Default background color used for all tables.
    @table-bg:                      transparent;
    //** Background color used for `.table-striped`.
    @table-bg-accent:               @gray-dark;
    //** Background color used for `.table-hover`.
    @table-bg-hover:                rgba(255,255,255,.075);
    @table-bg-active:               @table-bg-hover;
    
    //** Border color for table and cell borders.
    @table-border-color:            @component-active-bg;
    
    
    //== Buttons
    //
    //## For each of Bootstrap's buttons, define text, background and border color.
    
    @btn-font-weight:                normal;
    
    @btn-default-color:              #fff;
    @btn-default-bg:                 #586E75;
    @btn-default-border:             @btn-default-bg;
    
    @btn-primary-color:              #fff;
    @btn-primary-bg:                 @brand-primary;
    @btn-primary-border:             @btn-primary-bg;
    
    @btn-success-color:              #fff;
    @btn-success-bg:                 @brand-success;
    @btn-success-border:             @btn-success-bg;
    
    @btn-info-color:                 #fff;
    @btn-info-bg:                    @brand-info;
    @btn-info-border:                @btn-info-bg;
    
    @btn-warning-color:              #fff;
    @btn-warning-bg:                 @brand-warning;
    @btn-warning-border:             @btn-warning-bg;
    
    @btn-danger-color:               #fff;
    @btn-danger-bg:                  @brand-danger;
    @btn-danger-border:              @btn-danger-bg;
    
    @btn-link-disabled-color:        @gray-light;
    
    // Allows for customizing button radius independently from global border radius
    @btn-border-radius-base:         @border-radius-base;
    @btn-border-radius-large:        @border-radius-large;
    @btn-border-radius-small:        @border-radius-small;
    
    
    //== Forms
    //
    //##
    
    //** `` background color
    @input-bg:                       #A9BDBD;
    //** `` background color
    @input-bg-disabled:              #657B83;
    
    //** Text color for ``s
    @input-color:                    @gray-dark;
    //** `` border color
    @input-border:                   rgba(0, 0, 0, .15);
    
    // TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
    //** Default `.form-control` border radius
    // This has no effect on ``s in CSS.
    @input-border-radius:            @border-radius-base;
    //** Large `.form-control` border radius
    @input-border-radius-large:      @border-radius-large;
    //** Small `.form-control` border radius
    @input-border-radius-small:      @border-radius-small;
    
    //** Border color for inputs on focus
    @input-border-focus:             #66afe9;
    
    //** Placeholder text color
    @input-color-placeholder:        #657B83;
    
    //** Default `.form-control` height
    @input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);
    //** Large `.form-control` height
    @input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
    //** Small `.form-control` height
    @input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
    
    //** `.form-group` margin
    @form-group-margin-bottom:       15px;
    
    @legend-color:                   @text-color;
    @legend-border-color:            @component-active-bg;
    
    //** Background color for textual input addons
    @input-group-addon-bg:           @gray-dark;
    //** Border color for textual input addons
    @input-group-addon-border-color: @input-border;
    
    //** Disabled cursor for form controls and buttons.
    @cursor-disabled:                not-allowed;
    
    
    //== Dropdowns
    //
    //## Dropdown menu container and contents.
    
    //** Background for the dropdown menu.
    @dropdown-bg:                    @gray-dark;
    //** Dropdown menu `border-color`.
    @dropdown-border:                rgba(0,0,0,.15);
    //** Dropdown menu `border-color` **for IE8**.
    @dropdown-fallback-border:       #ccc;
    //** Divider color for between dropdown items.
    @dropdown-divider-bg:            @body-bg;
    
    //** Dropdown link text color.
    @dropdown-link-color:            @text-color;
    //** Hover color for dropdown links.
    @dropdown-link-hover-color:      rgba(255,255,255,.75);
    //** Hover background for dropdown links.
    @dropdown-link-hover-bg:         @body-bg;
    
    //** Active dropdown menu item text color.
    @dropdown-link-active-color:     @component-active-color;
    //** Active dropdown menu item background color.
    @dropdown-link-active-bg:        @component-active-bg;
    
    //** Disabled dropdown menu item background color.
    @dropdown-link-disabled-color:   @gray-light;
    
    //** Text color for headers within dropdown menus.
    @dropdown-header-color:          @gray-light;
    
    //** Deprecated `@dropdown-caret-color` as of v3.1.0
    @dropdown-caret-color:           #000;
    
    
    //-- Z-index master list
    //
    // Warning: Avoid customizing these values. They're used for a bird's eye view
    // of components dependent on the z-axis and are designed to all work together.
    //
    // Note: These variables are not generated into the Customizer.
    
    @zindex-navbar:            1000;
    @zindex-dropdown:          1000;
    @zindex-popover:           1060;
    @zindex-tooltip:           1070;
    @zindex-navbar-fixed:      1030;
    @zindex-modal-background:  1040;
    @zindex-modal:             1050;
    
    
    //== Media queries breakpoints
    //
    //## Define the breakpoints at which your layout will change, adapting to different screen sizes.
    
    // Extra small screen / phone
    //** Deprecated `@screen-xs` as of v3.0.1
    @screen-xs:                  480px;
    //** Deprecated `@screen-xs-min` as of v3.2.0
    @screen-xs-min:              @screen-xs;
    //** Deprecated `@screen-phone` as of v3.0.1
    @screen-phone:               @screen-xs-min;
    
    // Small screen / tablet
    //** Deprecated `@screen-sm` as of v3.0.1
    @screen-sm:                  768px;
    @screen-sm-min:              @screen-sm;
    //** Deprecated `@screen-tablet` as of v3.0.1
    @screen-tablet:              @screen-sm-min;
    
    // Medium screen / desktop
    //** Deprecated `@screen-md` as of v3.0.1
    @screen-md:                  992px;
    @screen-md-min:              @screen-md;
    //** Deprecated `@screen-desktop` as of v3.0.1
    @screen-desktop:             @screen-md-min;
    
    // Large screen / wide desktop
    //** Deprecated `@screen-lg` as of v3.0.1
    @screen-lg:                  1200px;
    @screen-lg-min:              @screen-lg;
    //** Deprecated `@screen-lg-desktop` as of v3.0.1
    @screen-lg-desktop:          @screen-lg-min;
    
    // So media queries don't overlap when required, provide a maximum
    @screen-xs-max:              (@screen-sm-min - 1);
    @screen-sm-max:              (@screen-md-min - 1);
    @screen-md-max:              (@screen-lg-min - 1);
    
    
    //== Grid system
    //
    //## Define your custom responsive grid.
    
    //** Number of columns in the grid.
    @grid-columns:              12;
    //** Padding between columns. Gets divided in half for the left and right.
    @grid-gutter-width:         30px;
    // Navbar collapse
    //** Point at which the navbar becomes uncollapsed.
    @grid-float-breakpoint:     @screen-sm-min;
    //** Point at which the navbar begins collapsing.
    @grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
    
    
    //== Container sizes
    //
    //## Define the maximum width of `.container` for different screen sizes.
    
    // Small screen / tablet
    @container-tablet:             (720px + @grid-gutter-width);
    //** For `@screen-sm-min` and up.
    @container-sm:                 @container-tablet;
    
    // Medium screen / desktop
    @container-desktop:            (940px + @grid-gutter-width);
    //** For `@screen-md-min` and up.
    @container-md:                 @container-desktop;
    
    // Large screen / wide desktop
    @container-large-desktop:      (1140px + @grid-gutter-width);
    //** For `@screen-lg-min` and up.
    @container-lg:                 @container-large-desktop;
    
    
    //== Navbar
    //
    //##
    
    // Basics of a navbar
    @navbar-height:                    50px;
    @navbar-margin-bottom:             @line-height-computed;
    @navbar-border-radius:             @border-radius-base;
    @navbar-padding-horizontal:        floor((@grid-gutter-width / 2));
    @navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);
    @navbar-collapse-max-height:       340px;
    
    @navbar-default-color:             @text-color;
    @navbar-default-bg:                @gray-dark;
    @navbar-default-border:            transparent;
    
    // Navbar links
    @navbar-default-link-color:                rgba(255,255,255,.5);
    @navbar-default-link-hover-color:          rgba(255,255,255,.75);
    @navbar-default-link-hover-bg:             transparent;
    @navbar-default-link-active-color:         #fff;
    @navbar-default-link-active-bg:            darken(@navbar-default-bg, 2.5%);
    @navbar-default-link-disabled-color:       rgba(255,255,255,.25);
    @navbar-default-link-disabled-bg:          transparent;
    
    // Navbar brand label
    @navbar-default-brand-color:               #fff;
    @navbar-default-brand-hover-color:         #fff;
    @navbar-default-brand-hover-bg:            transparent;
    
    // Navbar toggle
    @navbar-default-toggle-hover-bg:           @navbar-default-link-color;
    @navbar-default-toggle-icon-bar-bg:        @navbar-default-toggle-hover-bg;
    @navbar-default-toggle-border-color:       @navbar-default-link-disabled-color;
    
    
    //=== Inverted navbar
    // Reset inverted navbar basics
    @navbar-inverse-color:                      lighten(@gray-light, 15%);
    @navbar-inverse-bg:                         @brand-primary;
    @navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);
    
    // Inverted navbar links
    @navbar-inverse-link-color:                 @navbar-default-link-color;
    @navbar-inverse-link-hover-color:           @navbar-default-link-hover-color;
    @navbar-inverse-link-hover-bg:              transparent;
    @navbar-inverse-link-active-color:          #fff;
    @navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 10%);
    @navbar-inverse-link-disabled-color:        @navbar-default-link-disabled-color;
    @navbar-inverse-link-disabled-bg:           transparent;
    
    // Inverted navbar brand label
    @navbar-inverse-brand-color:                #fff;
    @navbar-inverse-brand-hover-color:          #fff;
    @navbar-inverse-brand-hover-bg:             transparent;
    
    // Inverted navbar toggle
    @navbar-inverse-toggle-hover-bg:            @navbar-inverse-link-color;
    @navbar-inverse-toggle-icon-bar-bg:         @navbar-inverse-toggle-hover-bg;
    @navbar-inverse-toggle-border-color:        @navbar-inverse-link-disabled-color;
    
    
    //== Navs
    //
    //##
    
    //=== Shared nav styles
    @nav-link-padding:                          10px 15px;
    @nav-link-hover-bg:                         transparent;
    
    @nav-disabled-link-color:                   @gray;
    @nav-disabled-link-hover-color:             @gray;
    
    //== Tabs
    @nav-tabs-border-color:                     @gray-dark;
    
    @nav-tabs-link-hover-border-color:          @nav-tabs-border-color;
    
    @nav-tabs-active-link-hover-bg:             @body-bg;
    @nav-tabs-active-link-hover-color:          #fff;
    @nav-tabs-active-link-hover-border-color:   @nav-tabs-border-color;
    
    @nav-tabs-justified-link-border-color:            @nav-tabs-border-color;
    @nav-tabs-justified-active-link-border-color:     @body-bg;
    
    //== Pills
    @nav-pills-border-radius:                   @border-radius-base;
    @nav-pills-active-link-hover-bg:            @component-active-bg;
    @nav-pills-active-link-hover-color:         @component-active-color;
    
    
    //== Pagination
    //
    //##
    
    @pagination-color:                     @link-color;
    @pagination-bg:                        transparent;
    @pagination-border:                    @component-active-bg;
    
    @pagination-hover-color:               @link-hover-color;
    @pagination-hover-bg:                  @component-active-bg;
    @pagination-hover-border:              @component-active-bg;
    
    @pagination-active-color:              rgba(255,255,255,.75);
    @pagination-active-bg:                 @component-active-bg;
    @pagination-active-border:             @component-active-bg;
    
    @pagination-disabled-color:            @component-active-bg;
    @pagination-disabled-bg:               transparent;
    @pagination-disabled-border:           @component-active-bg;
    
    
    //== Pager
    //
    //##
    
    @pager-bg:                             @pagination-bg;
    @pager-border:                         @pagination-border;
    @pager-border-radius:                  15px;
    
    @pager-hover-bg:                       @pagination-hover-bg;
    
    @pager-active-bg:                      @pagination-active-bg;
    @pager-active-color:                   @pagination-active-color;
    
    @pager-disabled-color:                 @pagination-disabled-color;
    
    
    //== Jumbotron
    //
    //##
    
    @jumbotron-padding:              30px;
    @jumbotron-color:                inherit;
    @jumbotron-bg:                   @component-active-bg;
    @jumbotron-heading-color:        inherit;
    @jumbotron-font-size:            ceil((@font-size-base * 1.5));
    @jumbotron-heading-font-size:    ceil((@font-size-base * 4.5));
    
    
    //== Form states and alerts
    //
    //## Define colors for form feedback states and, by default, alerts.
    
    @state-success-text:             #fff;
    @state-success-bg:               @brand-success;
    @state-success-border:           @state-success-bg;
    
    @state-info-text:                #fff;
    @state-info-bg:                  @brand-info;
    @state-info-border:              @state-info-bg;
    
    @state-warning-text:             #fff;
    @state-warning-bg:               @brand-warning;
    @state-warning-border:           @state-warning-bg;
    
    @state-danger-text:              #fff;
    @state-danger-bg:                @brand-danger;
    @state-danger-border:            @state-danger-bg;
    
    
    //== Tooltips
    //
    //##
    
    //** Tooltip max width
    @tooltip-max-width:           200px;
    //** Tooltip text color
    @tooltip-color:               #fff;
    //** Tooltip background color
    @tooltip-bg:                  #000;
    @tooltip-opacity:             .9;
    
    //** Tooltip arrow width
    @tooltip-arrow-width:         5px;
    //** Tooltip arrow color
    @tooltip-arrow-color:         @tooltip-bg;
    
    
    //== Popovers
    //
    //##
    
    //** Popover body background color
    @popover-bg:                          @component-active-bg;
    //** Popover maximum width
    @popover-max-width:                   276px;
    //** Popover border color
    @popover-border-color:                @body-bg;
    //** Popover fallback border color
    @popover-fallback-border-color:       #ccc;
    
    //** Popover title background color
    @popover-title-bg:                    @component-active-bg;
    
    //** Popover arrow width
    @popover-arrow-width:                 10px;
    //** Popover arrow color
    @popover-arrow-color:                 @popover-bg;
    
    //** Popover outer arrow width
    @popover-arrow-outer-width:           (@popover-arrow-width + 1);
    //** Popover outer arrow color
    @popover-arrow-outer-color:           fadein(@popover-border-color, 5%);
    //** Popover outer arrow fallback color
    @popover-arrow-outer-fallback-color:  darken(@popover-fallback-border-color, 20%);
    
    
    //== Labels
    //
    //##
    
    //** Default label background color
    @label-default-bg:            @btn-default-bg;
    //** Primary label background color
    @label-primary-bg:            @brand-primary;
    //** Success label background color
    @label-success-bg:            @brand-success;
    //** Info label background color
    @label-info-bg:               @brand-info;
    //** Warning label background color
    @label-warning-bg:            @brand-warning;
    //** Danger label background color
    @label-danger-bg:             @brand-danger;
    
    //** Default label text color
    @label-color:                 #fff;
    //** Default text color of a linked label
    @label-link-hover-color:      #fff;
    
    
    //== Modals
    //
    //##
    
    //** Padding applied to the modal body
    @modal-inner-padding:         15px;
    
    //** Padding applied to the modal title
    @modal-title-padding:         15px;
    //** Modal title line-height
    @modal-title-line-height:     @line-height-base;
    
    //** Background color of modal content area
    @modal-content-bg:                             @component-active-bg;
    //** Modal content border color
    @modal-content-border-color:                   @body-bg;
    //** Modal content border color **for IE8**
    @modal-content-fallback-border-color:          #999;
    
    //** Modal backdrop background color
    @modal-backdrop-bg:           #000;
    //** Modal backdrop opacity
    @modal-backdrop-opacity:      .5;
    //** Modal header border color
    @modal-header-border-color:   @modal-content-border-color;
    //** Modal footer border color
    @modal-footer-border-color:   @modal-header-border-color;
    
    @modal-lg:                    900px;
    @modal-md:                    600px;
    @modal-sm:                    300px;
    
    
    //== Alerts
    //
    //## Define alert colors, border radius, and padding.
    
    @alert-padding:               15px;
    @alert-border-radius:         @border-radius-base;
    @alert-link-font-weight:      bold;
    
    @alert-success-bg:            @state-success-bg;
    @alert-success-text:          @state-success-text;
    @alert-success-border:        @state-success-border;
    
    @alert-info-bg:               @state-info-bg;
    @alert-info-text:             @state-info-text;
    @alert-info-border:           @state-info-border;
    
    @alert-warning-bg:            @state-warning-bg;
    @alert-warning-text:          @state-warning-text;
    @alert-warning-border:        @state-warning-border;
    
    @alert-danger-bg:             @state-danger-bg;
    @alert-danger-text:           @state-danger-text;
    @alert-danger-border:         @state-danger-border;
    
    
    //== Progress bars
    //
    //##
    
    //** Background color of the whole progress component
    @progress-bg:                 @component-active-bg;
    //** Progress bar text color
    @progress-bar-color:          #fff;
    //** Variable for setting rounded corners on progress bar.
    @progress-border-radius:      @border-radius-base;
    
    //** Default progress bar color
    @progress-bar-bg:             @brand-primary;
    //** Success progress bar color
    @progress-bar-success-bg:     @brand-success;
    //** Warning progress bar color
    @progress-bar-warning-bg:     @brand-warning;
    //** Danger progress bar color
    @progress-bar-danger-bg:      @brand-danger;
    //** Info progress bar color
    @progress-bar-info-bg:        @brand-info;
    
    
    //== List group
    //
    //##
    
    //** Background color on `.list-group-item`
    @list-group-bg:                 transparent;
    //** `.list-group-item` border color
    @list-group-border:             @component-active-bg;
    //** List group border radius
    @list-group-border-radius:      @border-radius-base;
    
    //** Background color of single list items on hover
    @list-group-hover-bg:           @component-active-bg;
    //** Text color of active list items
    @list-group-active-color:       @component-active-color;
    //** Background color of active list items
    @list-group-active-bg:          @component-active-bg;
    //** Border color of active list elements
    @list-group-active-border:      @list-group-active-bg;
    //** Text color for content within active list items
    @list-group-active-text-color:  @component-active-color;
    
    //** Text color of disabled list items
    @list-group-disabled-color:      @component-active-bg;
    //** Background color of disabled list items
    @list-group-disabled-bg:         transparent;
    //** Text color for content within disabled list items
    @list-group-disabled-text-color: @list-group-disabled-color;
    
    @list-group-link-color:         @text-color;
    @list-group-link-hover-color:   @component-active-color;
    @list-group-link-heading-color: @text-color;
    
    
    //== Panels
    //
    //##
    
    @panel-bg:                    transparent;
    @panel-body-padding:          15px;
    @panel-heading-padding:       10px 15px;
    @panel-footer-padding:        @panel-heading-padding;
    @panel-border-radius:         @border-radius-base;
    
    //** Border color for elements within panels
    @panel-inner-border:          @component-active-bg;
    @panel-footer-bg:             @component-active-bg;
    
    @panel-default-text:          #fff;
    @panel-default-border:        @component-active-bg;
    @panel-default-heading-bg:    @component-active-bg;
    
    @panel-primary-text:          #fff;
    @panel-primary-border:        @brand-primary;
    @panel-primary-heading-bg:    @brand-primary;
    
    @panel-success-text:          @state-success-text;
    @panel-success-border:        @state-success-border;
    @panel-success-heading-bg:    @state-success-bg;
    
    @panel-info-text:             @state-info-text;
    @panel-info-border:           @state-info-border;
    @panel-info-heading-bg:       @state-info-bg;
    
    @panel-warning-text:          @state-warning-text;
    @panel-warning-border:        @state-warning-border;
    @panel-warning-heading-bg:    @state-warning-bg;
    
    @panel-danger-text:           @state-danger-text;
    @panel-danger-border:         @state-danger-border;
    @panel-danger-heading-bg:     @state-danger-bg;
    
    
    //== Thumbnails
    //
    //##
    
    //** Padding around the thumbnail image
    @thumbnail-padding:           4px;
    //** Thumbnail background color
    @thumbnail-bg:                @body-bg;
    //** Thumbnail border color
    @thumbnail-border:            #ddd;
    //** Thumbnail border radius
    @thumbnail-border-radius:     @border-radius-base;
    
    //** Custom text color for thumbnail captions
    @thumbnail-caption-color:     @text-color;
    //** Padding around the thumbnail caption
    @thumbnail-caption-padding:   9px;
    
    
    //== Wells
    //
    //##
    
    @well-bg:                     lighten(@component-active-bg, 2%);
    @well-border:                 transparent;
    
    
    //== Badges
    //
    //##
    
    @badge-color:                 #fff;
    //** Linked badge text color on hover
    @badge-link-hover-color:      #fff;
    @badge-bg:                    @btn-default-bg;
    
    //** Badge text color in active nav link
    @badge-active-color:          #fff;
    //** Badge background color in active nav link
    @badge-active-bg:             @badge-bg;
    
    @badge-font-weight:           bold;
    @badge-line-height:           1;
    @badge-border-radius:         10px;
    
    
    //== Breadcrumbs
    //
    //##
    
    @breadcrumb-padding-vertical:   8px;
    @breadcrumb-padding-horizontal: 15px;
    //** Breadcrumb background color
    @breadcrumb-bg:                 @component-active-bg;
    //** Breadcrumb text color
    @breadcrumb-color:              @gray;
    //** Text color of current page in the breadcrumb
    @breadcrumb-active-color:       @gray;
    //** Textual separator for between breadcrumb elements
    @breadcrumb-separator:          "/";
    
    
    //== Carousel
    //
    //##
    
    @carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);
    
    @carousel-control-color:                      #fff;
    @carousel-control-width:                      15%;
    @carousel-control-opacity:                    .5;
    @carousel-control-font-size:                  20px;
    
    @carousel-indicator-active-bg:                #fff;
    @carousel-indicator-border-color:             #fff;
    
    @carousel-caption-color:                      #fff;
    
    
    //== Close
    //
    //##
    
    @close-font-weight:           bold;
    @close-color:                 @text-color;
    @close-text-shadow:           none;
    
    
    //== Code
    //
    //##
    
    @code-color:                  #c7254e;
    @code-bg:                     #f9f2f4;
    
    @kbd-color:                   #fff;
    @kbd-bg:                      #333;
    
    @pre-bg:                      #f5f5f5;
    @pre-color:                   @gray-dark;
    @pre-border-color:            #ccc;
    @pre-scrollable-max-height:   340px;
    
    
    //== Type
    //
    //##
    
    //** Horizontal offset for forms and lists.
    @component-offset-horizontal: 180px;
    //** Text muted color
    @text-muted:                  @gray-light;
    //** Abbreviations and acronyms border color
    @abbr-border-color:           @gray-dark;
    //** Headings small color
    @headings-small-color:        @text-color;
    //** Blockquote small color
    @blockquote-small-color:      @text-color;
    //** Blockquote font size
    @blockquote-font-size:        (@font-size-base * 1.25);
    //** Blockquote border color
    @blockquote-border-color:     @gray-dark;
    //** Page header border color
    @page-header-border-color:    @component-active-bg;
    //** Width of horizontal description list titles
    @dl-horizontal-offset:        @component-offset-horizontal;
    //** Point at which .dl-horizontal becomes horizontal
    @dl-horizontal-breakpoint:    @grid-float-breakpoint;
    //** Horizontal line color.
    @hr-border:                   @gray-lighter;public/less/theme/spacelab.less000066400000000000000000000003201516067327100170510ustar00rootroot00000000000000
    @import "../../../node_modules/bootstrap/less/bootstrap";
    @import "../../../node_modules/bootswatch/spacelab/variables";
    @import "../../../node_modules/bootswatch/spacelab/bootswatch";
    @import "../default";
    public/less/theme/superhero.less000066400000000000000000000003221516067327100173150ustar00rootroot00000000000000
    @import "../../../node_modules/bootstrap/less/bootstrap";
    @import "../../../node_modules/bootswatch/superhero/variables";
    @import "../../../node_modules/bootswatch/superhero/bootswatch";
    @import "../default";
    public/less/theme/united.less000066400000000000000000000003141516067327100165720ustar00rootroot00000000000000
    @import "../../../node_modules/bootstrap/less/bootstrap";
    @import "../../../node_modules/bootswatch/united/variables";
    @import "../../../node_modules/bootswatch/united/bootswatch";
    @import "../default";
    public/less/theme/yeti.less000066400000000000000000000003101516067327100162500ustar00rootroot00000000000000
    @import "../../../node_modules/bootstrap/less/bootstrap";
    @import "../../../node_modules/bootswatch/yeti/variables";
    @import "../../../node_modules/bootswatch/yeti/bootswatch";
    @import "../default";
    public/less/treegraph.less000066400000000000000000000033741516067327100161720ustar00rootroot00000000000000.p3x-gitlist-treegraph-log {
    }
    
    .treegraph-button {
      padding: @padding-base-vertical !important;
      font-family: monospace;
    }
    
    
    .p3x-gitlist-light {
      .treegraph-button {
        background-color: @navbar-default-bg !important;
        color: @navbar-default-link-hover-color !important;
      }
      .treegraph-link {
        color: @brand-primary !important;
      }
    }
    
    .p3x-gitlist-dark {
      .treegraph-button {
        background-color: @navbar-inverse-bg !important;
        color: @navbar-inverse-link-hover-color !important;
      }
      .treegraph-link {
        color: @brand-primary !important;
      }
    }
    
    .network-view {
      width: 100%;
      margin-bottom: @line-height-base;
      position: relative;
    
    
      &.loading-commits {
    
        &:before {
          content: "";
          display: block;
          height: 100px;
          width: 200px;
          box-sizing: border-box;
          padding: 10px;
          font-weight: bold;
          position: absolute;
    
          left: 50%;
          top: 50%;
          margin-left: -100px;
          margin-top: -50px;
    
          z-index: 2000;
        }
    
        .network-header .meta:after {
          content: " - Loading";
        }
      }
    
      .network-header {
      }
      pre {
        margin: 0;
        padding: 12px;
        border: none;
      }
      .network-graph {
        height: 400px;
        overflow: hidden;
        cursor: move;
        position: relative;
        border: 1px solid @table-border-color;
    
    
        .network-commit-overlay {
          position: absolute;
          width: 400px;
          top: 0;
          left: 0;
          padding: 8px;
          margin: 0 0 @line-height-base;
          list-style: none;
          background-color: @navbar-default-bg;
          color: @navbar-default-color;
    
          a, a:active {
            background-color: @navbar-default-bg;
            color: @navbar-inverse-color;
          }
    
          img {
            float: left;
            margin-right: 10px;
          }
    
          div {
          }
        }
    
      }
    }scripts/000077500000000000000000000000001516067327100125555ustar00rootroot00000000000000scripts/init.sh000077500000000000000000000015541516067327100140640ustar00rootroot00000000000000#!/usr/bin/env bash
    DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    set -e
    sudo rm -rf ./cache
    mkdir -p ./cache
    touch ./cache/.gitkeep
    chmod 0770 ./cache
    
    sudo rm -rf ./git-test/
    mkdir -p ./git-test/
    
    pushd ./git-test
    
    for repo in "https://github.com/patrikx3/gitlist" "https://github.com/patrikx3/gitter" "https://github.com/patrikx3/corifeus" "https://github.com/patrikx3/corifeus-builder" "https://github.com/patrikx3/gitlist-workspace" "https://github.com/patrikx3/onenote" "https://github.com/patrikx3/resume-web"
    do
        git clone --bare $repo
    done
    
    find . -name '*description*' |
    while read filename;
    do
        echo "$(dirname ${filename:2} | cut -f 1 -d '.') test repository." > $filename
    done
    
    popd
    
    sudo chmod 0777 ./git-test
    cp ./artifacts/config.ini ./
    
    composer install
    
    chown $USER:$USER ./cache
    chown $USER:$USER ./git-test
    chown $USER:$USER ./config.ini
    
    
    scripts/optimize.sh000077500000000000000000000004441516067327100147560ustar00rootroot00000000000000#!/usr/bin/env bash
    DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    TOP=$DIR/..
    set -e
    pushd $TOP
    sudo rm -rf ./cache
    mkdir -p ./cache
    touch ./cache/.gitkeep
    chmod 0770 ./cache
    composer install
    composer install --no-dev
    composer dump-autoload --optimize
    npm install
    npm run build
    popdscripts/release.sh000077500000000000000000000017601516067327100145400ustar00rootroot00000000000000#!/usr/bin/env bash
    DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    TOP=$DIR/..
    
    set -e
    
    version=$( node -e "console.log(require('$TOP/package.json').version)" )
    pkg_name=$( node -e "console.log(require('$TOP/package.json').name)" )
    name=$pkg_name-$version
    repo=$TOP/build/$name
    
    pushd $TOP
    composer install --no-dev
    composer dump-autoload --optimize
    #npm install
    npm run build
    
    rm -rf $repo || true
    mkdir -p $repo
    
    for item in "$TOP/cache" "$TOP/src" "$TOP/public" "$TOP/vendor" "$TOP/twig"
    do
        echo $item
        cp -R $item $repo/
    done
    
    for item in "$TOP/INSTALL.md" "$TOP/LICENSE" "$TOP/README.md" "$TOP/boot.php" "$TOP/config.example.ini" "$TOP/package.json"
    do
        echo $item
        cp $item $repo/
    done
    
    rm -rf $repo/public/less
    rm -rf $repo/public/js
    
    zipname=$TOP/build/$name.zip
    rm -rf $zipname
    pushd $repo
    zip -r $TOP/build/$name.zip * .*
    popd
    
    RELEASE=$TOP/build/release
    rm -rf $RELEASE || true
    mv $repo $RELEASE
    cp $TOP/config.ini $RELEASE || true
    cp -R $TOP/git-test $RELEASE/ || true
    
    popdsrc/000077500000000000000000000000001516067327100116555ustar00rootroot00000000000000src/Application.php000077500000000000000000000176311516067327100146440ustar00rootroot00000000000000path = realpath($root);
    
            $string = file_get_contents("../package.json");
            $pkg = json_decode($string, true);
    
            $this['url_subdir'] = dirname($_SERVER['SCRIPT_NAME']);
            if ($this['url_subdir'] === '/') {
                $this['url_subdir'] = '';
            }
            $this['debug'] = $config->get('app', 'debug');
            $this['date.format'] = $config->get('date', 'format') ? $config->get('date', 'format') : 'd/m/Y H:i:s';
            $this['theme'] = 'bootstrap';
    
            $this['title'] = $config->get('app', 'title') ? $config->get('app', 'title') : 'P3X GitList ' . $pkg['version'];
            $this['filetypes'] = $config->getSection('filetypes');
            $this['binary_filetypes'] = $config->getSection('binary_filetypes');
            $this['cache.archives'] = $this->getCachePath() . 'archives';
            $this['avatar.url'] = $config->get('avatar', 'url');
            $this['avatar.query'] = $config->get('avatar', 'query');
            $this['show_http_remote'] = $config->get('clone_button', 'show_http_remote');
            $this['use_https'] = $config->get('clone_button', 'use_https');
            $this['git_clone_subdir'] = $config->get('clone_button', 'git_clone_subdir');
            $this['http_user'] = $config->get('clone_button', 'http_user_dynamic') ? $_SERVER['PHP_AUTH_USER'] : $config->get('clone_button', 'http_user');
            $this['show_ssh_remote'] = $config->get('clone_button', 'show_ssh_remote');
            $this['ssh_user'] = $config->get('clone_button', 'ssh_user');
    
            // Register services
            $this->register(new TwigServiceProvider(), array(
                'twig.path'       => array($this->getThemePath($this['theme'])),
                'twig.options'    => $config->get('app', 'cache') ?
                                     array('cache' => $this->getCachePath() . 'views') : array(),
            ));
    
            $repositories = $config->get('git', 'repositories');
            $this['git.projects'] = $config->get('git', 'project_list') ?
                                    $this->parseProjectList($config->get('git', 'project_list')) :
                                    false;
    
            $this->register(new GitServiceProvider(), array(
                'config'            => $config,
                'git.client'         => $config->get('git', 'client'),
                'git.repos'          => $repositories,
                'ini.file'           => "config.ini",
                'git.hidden'         => $config->get('git', 'hidden') ?
                                        $config->get('git', 'hidden') : array(),
                'git.default_branch' => $config->get('git', 'default_branch') ?
                                        $config->get('git', 'default_branch') : 'master',
            ));
    
            $this->register(new ViewUtilServiceProvider());
            $this->register(new RepositoryUtilServiceProvider());
            $this->register(new RoutingUtilServiceProvider());
    
            $this['twig'] =  $this->extend('twig', function ($twig, $app) use ($pkg) {
    
                $twig->addFilter(new \Twig_SimpleFilter('to_id', function($value) {
                    $value = str_replace(['.', '/', '\\', ' '], '-', $value);
                    $value = strtolower($value);
                    return $value;
                }));
    
                $twig->addFilter(new \Twig_SimpleFilter('remove_extension', function ($string) {
                    return pathinfo($string, PATHINFO_FILENAME);
                }));
    
    
                $twig->addFilter(new \Twig_SimpleFilter('htmlentities', 'htmlentities'));
                $twig->addFilter(new \Twig_SimpleFilter('md5', 'md5'));
                $twig->addFilter(new \Twig_SimpleFilter('format_date', array($app, 'formatDate')));
                $twig->addFilter(new \Twig_SimpleFilter('format_size', array($app, 'formatSize')));
                $twig->addFunction(new \Twig_SimpleFunction('avatar', array($app, 'getAvatar')));
    
                $currentTheme = !isset($_COOKIE['gitlist-bootstrap-theme']) ? 'bootstrap-cosmo' : $_COOKIE['gitlist-bootstrap-theme'];
                $themeDark = [
                    'cyborg',
                    'darkly',
                    'slate',
                    'superhero',
                    'solar',
                ];
    
                $twig->addGlobal('theme_type', !in_array(substr($currentTheme, strlen('bootstrap-')), $themeDark) ? 'p3x-gitlist-light' : 'p3x-gitlist-dark');
    
                $twig->addGlobal('theme', $currentTheme);
                $query = isset($_REQUEST['query']) ? $_REQUEST['query'] : (isset($_COOKIE['p3x-gitlist-query']) ? $_COOKIE['p3x-gitlist-query'] : '');
    
                setcookie('p3x-gitlist-query',$query,0, '/' . $this['url_subdir']);
    
                $_COOKIE['p3x-gitlist-query'] = $query;
    
                $twig->addGlobal('search_query', $query);
    
                $postfixFile = __DIR__ . '/css-postfix';
                $twig->addGlobal('theme_postfix', file_get_contents($postfixFile));
    
                $twig->addGlobal('theme_dark', $themeDark);
    
                $twig->addGlobal('version', $pkg['version']);
                $twig->addGlobal('gitlist_date_format', $this['date.format']);
    
                return $twig;
            });
    
            $this['escaper.argument'] = $this->factory(function() {
                return new Escaper\ArgumentEscaper();
            });
    
            // Handle errors
            $this->error(function (\Exception $e, $code) use ($app) {
                if ($app['debug']) {
                    return;
                }
    
                return $app['twig']->render('error.twig', array(
                    'message' => $e->getMessage(),
                ));
            });
    
            $this->finish(function () use ($app, $config) {
                if (!$config->get('app', 'cache')) {
                    $fs = new Filesystem();
                    $fs->remove($app['cache.archives']);
                }
            });
        }
    
        public function formatDate($date)
        {
            return $date->format($this['date.format']);
        }
    
        public function formatSize($size)
        {
            $mod = 1000;
            $units = array('B', 'kB', 'MB', 'GB');
            for($i = 0; $size > $mod; $i++) $size /= $mod;
            return round($size, 2) . " " . $units[$i];
        }
    
        public function getAvatar($email, $size)
        {
            $url = $this['avatar.url'] ? $this['avatar.url'] : "//gravatar.com/avatar/";
            $query = array("s=$size");
            if (is_string($this['avatar.query']))
                $query[] = $this['avatar.query'];
            else if (is_array($this['avatar.query']))
                $query = array_merge($query, $this['avatar.query']);
            $id = md5(strtolower($email));
            return $url . $id . "?" . implode('&', $query);
        }
    
        public function getPath()
        {
            return $this->path . DIRECTORY_SEPARATOR;
        }
    
        public function setPath($path)
        {
            $this->path = $path;
    
            return $this;
        }
    
        public function getCachePath()
        {
            return $this->path
                . DIRECTORY_SEPARATOR
                . 'cache'
                . DIRECTORY_SEPARATOR;
        }
    
        public function getThemePath($theme)
        {
            return $this->path
                . DIRECTORY_SEPARATOR
                . 'twig'
                . DIRECTORY_SEPARATOR;
        }
    
        public function parseProjectList($project_list)
        {
            $projects = array();
            $file = fopen($project_list, "r");
            while ($file && !feof($file))
                $projects[] = trim(fgets($file));
            fclose($file);
            return $projects;
        }
    }
    src/Config.php000066400000000000000000000033371516067327100136010ustar00rootroot00000000000000validateOptions();
    
            return $config;
        }
    
        public function __construct($data = array())
        {
            $this->data = $data;
        }
    
        public function get($section, $option)
        {
            if (!array_key_exists($section, $this->data)) {
                return false;
            }
    
            if (!array_key_exists($option, $this->data[$section])) {
                return false;
            }
    
            return $this->data[$section][$option];
        }
    
        public function getSection($section)
        {
            if (!array_key_exists($section, $this->data)) {
                return false;
            }
    
            return $this->data[$section];
        }
    
        public function set($section, $option, $value)
        {
            $this->data[$section][$option] = $value;
        }
    
        protected function validateOptions()
        {
            $repositories = $this->get('git', 'repositories');
    
            $atLeastOneOk = false;
            $atLeastOneWrong = false;
    
            foreach ($repositories as $directory) {
                if (!$directory || !is_dir($directory)) {
                    $atLeastOneWrong = true;
                } else {
                    $atLeastOneOk = true;
                }
            }
    
            if (!$atLeastOneOk) {
                die("Please, edit the config file and provide your repositories directory");
            }
    
            if ($atLeastOneWrong) {
                die("One or more of the supplied repository paths appears to be wrong. Please, check the config file");
            }
        }
    }
    
    src/Controller/000077500000000000000000000000001516067327100140005ustar00rootroot00000000000000src/Controller/BlobController.php000066400000000000000000000070051516067327100174350ustar00rootroot00000000000000get('app', 'codemirror_full_limit');
            if (!is_int($codemirror_full_limit) || $codemirror_full_limit < 32) {
                $codemirror_full_limit = 32;
            }
    
            $route->get('{repo}/blob/{commitishPath}', function ($repo, $commitishPath) use ($app, $codemirror_full_limit) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                list($branch, $file) = $app['util.routing']
                    ->parseCommitishPathParam($commitishPath, $repo);
    
                list($branch, $file) = $app['util.repository']->extractRef($repository, $branch, $file);
    
                $blob = $repository->getBlob("$branch:\"$file\"");
                $breadcrumbs = $app['util.view']->getBreadcrumbs($file);
                $fileType = $app['util.repository']->getFileType($file);
    
                if ($fileType !== 'image' && $app['util.repository']->isBinary($file)) {
                    return $app->redirect($app['url_generator']->generate('blob_raw', array(
                        'repo'   => $repo,
                        'commitishPath' => $commitishPath,
                    )));
                }
    
                $output = $blob->output();
    
                return $app['twig']->render('file.twig', array(
                    'fileSize'       => strlen($output),
                    'codemirror_full_limit' => $codemirror_full_limit,
                    'file'           => $file,
                    'fileType'       => $fileType,
                    'blob'           => $output,
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'breadcrumbs'    => $breadcrumbs,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => 'blob',
                    'tags'           => $repository->getTags(),
                    'enforceCodemirror' => isset($_GET['codemirror'])
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('commitishPath', '.+')
              ->convert('commitishPath', 'escaper.argument:escape')
              ->bind('blob');
    
            $route->get('{repo}/raw/{commitishPath}', function ($repo, $commitishPath) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                list($branch, $file) = $app['util.routing']
                    ->parseCommitishPathParam($commitishPath, $repo);
    
                list($branch, $file) = $app['util.repository']->extractRef($repository, $branch, $file);
    
                $blob = $repository->getBlob("$branch:\"$file\"")->output();
    
                $headers = array();
                if ($app['util.repository']->isBinary($file)) {
                    $headers['Content-Disposition'] = 'attachment; filename="' .  $file . '"';
                    $headers['Content-Type'] = 'application/octet-stream';
                } else {
                    $headers['Content-Type'] = 'text/plain';
                }
    
                return new Response($blob, 200, $headers);
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
              ->convert('commitishPath', 'escaper.argument:escape')
              ->bind('blob_raw');
    
            return $route;
        }
    }
    
    src/Controller/CommitController.php000066400000000000000000000136631516067327100200160ustar00rootroot00000000000000get('{repo}/commits/search', function (Request $request, $repo) use ($app) {
                $subRequest = Request::create(
                    '/' . $repo . '/commits/master/search',
                    'POST',
                    array('query' => $request->get('query'))
                );
                return $app->handle($subRequest, \Symfony\Component\HttpKernel\HttpKernelInterface::SUB_REQUEST);
            })->assert('repo', $app['util.routing']->getRepositoryRegex());
    
            $route->get('{repo}/commits/{commitishPath}', function ($repo, $commitishPath) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                if ($commitishPath === null) {
                    $commitishPath = $repository->getHead();
                }
    
                list($branch, $file) = $app['util.routing']
                    ->parseCommitishPathParam($commitishPath, $repo);
    
                list($branch, $file) = $app['util.repository']->extractRef($repository, $branch, $file);
    
                $type = $file ? "$branch -- \"$file\"" : $branch;
                $pager = $app['util.view']->getPager($app['request_stack']->getCurrentRequest()->get('page'), $repository->getTotalCommits($type));
                $commits = $repository->getPaginatedCommits($type, $pager['current']);
                $categorized = array();
    
    
                foreach ($commits as $commit) {
                    $date = $commit->getCommiterDate();
                    $date = $date->format('Y-m-d');
                    $categorized[$date][] = $commit;
                }
    
                $template = $app['request_stack']->getCurrentRequest()->isXmlHttpRequest() ? 'commits_list.twig' : 'commits.twig';
    
                return $app['twig']->render($template, array(
                    'page'           => 'commits',
                    'pager'          => $pager,
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => pathinfo($template)['filename'],
                    'tags'           => $repository->getTags(),
                    'commits'        => $categorized,
                    'file'           => $file,
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
              ->value('commitishPath', null)
              ->convert('commitishPath', 'escaper.argument:escape')
              ->bind('commits');
    
            $route->post('{repo}/commits/{branch}/search', function (Request $request, $repo, $branch = '') use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
                $query = $request->get('query');
    
                $commits = $repository->searchCommitLog($query, $branch);
                $categorized = array();
    
                foreach ($commits as $commit) {
                    $date = $commit->getCommiterDate();
                    $date = $date->format('Y-m-d');
                    $categorized[$date][] = $commit;
                }
    
                return $app['twig']->render('searchcommits.twig', array(
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'file'           => '',
                    'commits'        => $categorized,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => 'searchcommits',
                    'tags'           => $repository->getTags(),
                    'query'          => $query
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('branch', $app['util.routing']->getBranchRegex())
              ->convert('branch', 'escaper.argument:escape')
              ->bind('searchcommits');
    
            $route->get('{repo}/commit/{commit}', function ($repo, $commit) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
                $commit = $repository->getCommit($commit);
                $branch = $repository->getHead();
    
                return $app['twig']->render('commit.twig', array(
                    'branches'       => $repository->getBranches(),
                    'tags'           => $repository->getTags(),
                    'browse_type'    => 'commit',
                    'branch'         => $branch,
                    'repo'           => $repo,
                    'commit'         => $commit,
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('commit', '[a-f0-9^]+')
              ->bind('commit');
    
            $route->get('{repo}/blame/{commitishPath}', function ($repo, $commitishPath) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                list($branch, $file) = $app['util.routing']
                    ->parseCommitishPathParam($commitishPath, $repo);
    
                list($branch, $file) = $app['util.repository']->extractRef($repository, $branch, $file);
    
                $blames = $repository->getBlame("$branch -- \"$file\"");
    
                return $app['twig']->render('blame.twig', array(
                    'file'           => $file,
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => 'blame',
                    'tags'           => $repository->getTags(),
                    'blames'         => $blames,
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
              ->convert('commitishPath', 'escaper.argument:escape')
              ->bind('blame');
    
            return $route;
        }
    }
    
    src/Controller/GitController.php000066400000000000000000000031531516067327100173020ustar00rootroot00000000000000post('{repo}/git-helper/{branch}/save', function (Request $request, $repo, $branch = '') use ($app) {
                $repository = ($app['git']->getRepositoryFromName($app['git.repos'], $repo));
    
                $hadError = false;
    
                try {
                    if ($repository instanceof Repository && $app instanceof GitlistApp) {
                        $filename = $request->get('filename');
                        $value = $request->get('value');
                        $email = $request->get('email');
                        $name = $request->get('name');
                        $comment = $request->get('comment');
                        $objectResult = $repository->changeFile($app->getCachePath(), $repo, $branch, $filename, $value, $name, $email, $comment);
                        return json_encode($objectResult);
                    }
                } catch(\Throwable $e) {
                    $hadError = $e;
                } finally {
                    if ($hadError !== false) {
                        return json_encode((object) [
                            'status' => 'error',
                            'error' => true,
                            'message' => $hadError->getMessage(),
                        ]);
                    }
                }
            });
    
            return $route;
        }
    }
    
    src/Controller/MainController.php000066400000000000000000000054641516067327100174520ustar00rootroot00000000000000get('/', function() use ($app) {
                $repositories = $app['git']->getRepositories($app['git.repos']);
    
                return $app['twig']->render('index.twig', array(
                    'repositories'   => $repositories,
                ));
            })->bind('homepage');
    
            $route->get('/refresh', function(Request $request) use ($app ) {
                # Go back to calling page
                return $app->redirect($request->headers->get('Referer'));
            })->bind('refresh');
    
            $route->get('{repo}/stats/{branch}', function($repo, $branch) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                if ($branch === null) {
                    $branch = $repository->getHead();
                }
    
                $stats = $repository->getStatistics($branch);
                $authors = $repository->getAuthorStatistics($branch);
    
                return $app['twig']->render('stats.twig', array(
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => 'stats',
                    'tags'           => $repository->getTags(),
                    'stats'          => $stats,
                    'authors'        => $authors,
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('branch', $app['util.routing']->getBranchRegex())
              ->value('branch', null)
              ->convert('branch', 'escaper.argument:escape')
              ->bind('stats');
    
            $route->get('{repo}/{branch}/rss/', function($repo, $branch) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                if ($branch === null) {
                    $branch = $repository->getHead();
                }
    
                $commits = $repository->getPaginatedCommits($branch);
    
                $html = $app['twig']->render('rss.twig', array(
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'commits'        => $commits,
                ));
    
                return new Response($html, 200, array('Content-Type' => 'application/rss+xml'));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('branch', $app['util.routing']->getBranchRegex())
              ->value('branch', null)
              ->convert('branch', 'escaper.argument:escape')
              ->bind('rss');
    
            return $route;
        }
    }
    src/Controller/NetworkController.php000066400000000000000000000120711516067327100202070ustar00rootroot00000000000000get('{repo}/network/{commitishPath}/{page}.json',
                function ($repo, $commitishPath, $page) use ($app) {
                    /** @var $repository Repository */
                    $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                    if ($commitishPath === null) {
                        $commitishPath = $repository->getHead();
                    }
    
                    $pager = $app['util.view']->getPager($page, $repository->getTotalCommits($commitishPath));
                    $commits = $repository->getPaginatedCommits($commitishPath, $pager['current']);
    
                    $jsonFormattedCommits = array();
    
                    foreach ($commits as $commit) {
                        $detailsUrl = $app['url_generator']->generate(
                            'commit',
                            array(
                                'repo' => $repo,
                                'commit' => $commit->getHash()
                            )
                        );
    
                        $jsonFormattedCommits[$commit->getHash()] = array(
                            'hash' => $commit->getHash(),
                            'parentsHash' => $commit->getParentsHash(),
                            'date' => $commit->getDate()->format('U'),
                            'message' => htmlentities($commit->getMessage()),
                            'details' => $detailsUrl,
                            'author' => array(
                                'name' => $commit->getAuthor()->getName(),
                                'email' => $commit->getAuthor()->getEmail(),
                                'image' => $app->getAvatar($commit->getAuthor()->getEmail(), 40)
                            )
                        );
                    }
    
                    $nextPageUrl = null;
    
                    if ($pager['last'] !== $pager['current']) {
                        $nextPageUrl = $app['url_generator']->generate(
                            'networkData',
                            array(
                                'repo' => $repo,
                                'commitishPath' => $commitishPath,
                                'page' => $pager['next']
                            )
                        );
                    }
    
                    // when no commits are given, return an empty response - issue #369
                    if (count($commits) === 0) {
                        return $app->json(
                            array(
                                'repo' => $repo,
                                'commitishPath' => $commitishPath,
                                'nextPage' => null,
                                'start' => null,
                                'commits' => $jsonFormattedCommits
                                ), 200
                            );
                    }
    
                    return $app->json( array(
                        'repo' => $repo,
                        'commitishPath' => $commitishPath,
                        'nextPage' => $nextPageUrl,
                        'start' => $commits[0]->getHash(),
                        'commits' => $jsonFormattedCommits
                        ), 200
                    );
                }
            )->assert('repo', $app['util.routing']->getRepositoryRegex())
            ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
            ->value('commitishPath', null)
            ->convert('commitishPath', 'escaper.argument:escape')
            ->assert('page', '\d+')
            ->value('page', '0')
            ->bind('networkData');
    
            $route->get(
                '{repo}/network/{commitishPath}',
                function ($repo, $commitishPath) use ($app) {
                    $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                    if ($commitishPath === null) {
                        $commitishPath = $repository->getHead();
                    }
    
                    list($branch, $file) = $app['util.routing']->parseCommitishPathParam($commitishPath, $repo);
                    list($branch, $file) = $app['util.repository']->extractRef($repository, $branch, $file);
    
                    return $app['twig']->render(
                        'network.twig',
                        array(
                            'branches'       => $repository->getBranches(),
                            'tags'           => $repository->getTags(),
                            'browse_type'    => 'network',
                            'repo' => $repo,
                            'branch' => $branch,
                            'commitishPath' => $commitishPath,
                        )
                    );
                }
            )->assert('repo', $app['util.routing']->getRepositoryRegex())
            ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
            ->value('commitishPath', null)
            ->convert('commitishPath', 'escaper.argument:escape')
            ->bind('network');
    
            return $route;
        }
    }
    src/Controller/TreeController.php000066400000000000000000000130541516067327100174570ustar00rootroot00000000000000get('{repo}/tree/{commitishPath}/', $treeController = function ($repo, $commitishPath = '') use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
                $head = $repository->getHead();
                if (!$commitishPath) {
                    $commitishPath = $head;
                }
    
                list($branch, $tree) = $app['util.routing']->parseCommitishPathParam($commitishPath, $repo);
    
                list($branch, $tree) = $app['util.repository']->extractRef($repository, $branch, $tree);
                $files = $repository->getTree($tree ? "$branch:\"$tree\"/" : $branch);
                $breadcrumbs = $app['util.view']->getBreadcrumbs($tree);
    
                $parent = null;
                if (($slash = strrpos($tree, '/')) !== false) {
                    $parent = substr($tree, 0, $slash);
                } elseif (!empty($tree)) {
                    $parent = '';
                }
    
                return $app['twig']->render('tree.twig', array(
                    'head'           => $head,
                    'files'          => $files->output(),
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'path'           => $tree ? $tree . '/' : $tree,
                    'parent'         => $parent,
                    'breadcrumbs'    => $breadcrumbs,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => 'tree',
                    'tags'           => $repository->getTags(),
                    'readme'         => $app['util.repository']->getReadme($repository, $branch, $tree ? "$tree" : ""),
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
              ->convert('commitishPath', 'escaper.argument:escape')
              ->bind('tree');
    
            $route->post('{repo}/tree/{branch}/search', function (Request $request, $repo, $branch = '', $tree = '') use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
                if (!$branch) {
                    $branch = $repository->getHead();
                }
    
                $query = $request->get('query');
                $breadcrumbs = array(array('dir' => 'Search results for: ' . $query, 'path' => ''));
                $results = $repository->searchTree($query, $branch);
    
                return $app['twig']->render('search.twig', array(
                    'results'        => $results,
                    'repo'           => $repo,
                    'branch'         => $branch,
                    'path'           => $tree,
                    'breadcrumbs'    => $breadcrumbs,
                    'branches'       => $repository->getBranches(),
                    'browse_type'    => 'search',
                    'tags'           => $repository->getTags(),
                    'query'          => $query
                ));
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('branch', $app['util.routing']->getBranchRegex())
              ->convert('branch', 'escaper.argument:escape')
              ->bind('search');
    
            $route->get('{repo}/{format}ball/{branch}', function($repo, $format, $branch) use ($app) {
                $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                $tree = $repository->getBranchTree($branch);
    
                if (false === $tree) {
                    return $app->abort(404, 'Invalid commit or tree reference: ' . $branch);
                }
    
                $file = $app['cache.archives'] . DIRECTORY_SEPARATOR
                        . $repo . DIRECTORY_SEPARATOR
                        . substr($tree, 0, 2) . DIRECTORY_SEPARATOR
                        . substr($tree, 2)
                        . '.'
                        . $format;
    
                if (!file_exists($file)) {
                    $repository->createArchive($tree, $file, $format);
                }
    
                /**
                 * Generating name for downloading, lowercasing and removing all non
                 * ascii and special characters
                 */
                $filename = strtolower($repo.'_'.$branch);
                $filename = preg_replace('#[^a-z0-9]+#', '_', $filename);
                $filename = $filename . '.' . $format;
    
                $response = new BinaryFileResponse($file);
                $response->setContentDisposition('attachment', $filename);
                return $response;
            })->assert('format', '(zip|tar)')
              ->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('branch', $app['util.routing']->getBranchRegex())
              ->convert('branch', 'escaper.argument:escape')
              ->bind('archive');
    
    
            $route->get('{repo}/{branch}/', function($repo, $branch) use ($app, $treeController) {
                return $treeController($repo, $branch);
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->assert('branch', $app['util.routing']->getBranchRegex())
              ->convert('branch', 'escaper.argument:escape')
              ->bind('branch');
    
            $route->get('{repo}/', function($repo) use ($app, $treeController) {
                return $treeController($repo);
            })->assert('repo', $app['util.routing']->getRepositoryRegex())
              ->bind('repository');
    
            return $route;
        }
    }
    
    src/Controller/TreeGraphController.php000066400000000000000000000061251516067327100204420ustar00rootroot00000000000000get(
                '{repo}/treegraph/{commitishPath}',
                function ($repo, $commitishPath) use ($app) {
    
                    $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
                    $command = 'log --graph --date-order --all -C -M -n 100 --date=iso ' .
                        '--pretty=format:"B[%d] C[%H] D[%ad] A[%an] E[%ae] H[%h] S[%s]"';
                    $rawRows = $repository->getClient()->run($repository, $command);
                    $rawRows = explode("\n", $rawRows);
                    $graphItems = array();
    
                    foreach ($rawRows as $row) {
                        if (preg_match("/^(.+?)(\s(B\[(.*?)\])? C\[(.+?)\] D\[(.+?)\] A\[(.+?)\] E\[(.+?)\] H\[(.+?)\] S\[(.+?)\])?$/", $row, $output)) {
                            if (!isset($output[4])) {
                                $graphItems[] = array(
                                    "relation"=>$output[1]
                                );
                                continue;
                            }
                            $graphItems[] = array(
                                "relation"=>$output[1],
                                "branch"=>$output[4],
                                "rev"=>$output[5],
                                "date"=>$output[6],
                                "author"=>$output[7],
                                "author_email"=>$output[8],
                                "short_rev"=>$output[9],
                                "subject"=>preg_replace('/(^|\s)(#[[:xdigit:]]+)(\s|$)/', '$1$2$3', $output[10])
                            );
                        }
                    }
                    if ($commitishPath === null) {
                        $commitishPath = $repository->getHead();
                    }
    
                    list($branch, $file) = $app['util.routing']->parseCommitishPathParam($commitishPath, $repo);
                    list($branch, $file) = $app['util.repository']->extractRef($repository, $branch, $file);
    
                    return $app['twig']->render(
                        'treegraph.twig',
                        array(
                            'repo' => $repo,
                            'branch' => $branch,
                            'branches'       => $repository->getBranches(),
                            'tags'           => $repository->getTags(),
                            'browse_type'    => 'treegraph',
                            'commitishPath' => $commitishPath,
                            'graphItems' => $graphItems,
                        )
                    );
                }
            )->assert('repo', $app['util.routing']->getRepositoryRegex())
                ->assert('commitishPath', $app['util.routing']->getCommitishPathRegex())
                ->value('commitishPath', null)
                ->convert('commitishPath', 'escaper.argument:escape')
                ->bind('treegraph');
    
            return $route;
        }
    }
    src/Escaper/000077500000000000000000000000001516067327100132375ustar00rootroot00000000000000src/Escaper/ArgumentEscaper.php000066400000000000000000000003371516067327100170400ustar00rootroot00000000000000factory(function () use ($app) {
                return new Repository($app);
            });
        }
    
        public function boot(Container $app)
        {
        }
    }
    src/Provider/RoutingUtilServiceProvider.php000066400000000000000000000010751516067327100215040ustar00rootroot00000000000000factory(function () use ($app) {
                return new Routing($app);
            });
        }
    
        public function boot(Container $app)
        {
        }
    }
    src/Provider/ViewUtilServiceProvider.php000066400000000000000000000010411516067327100207600ustar00rootroot00000000000000factory(function () {
                return new View;
            });
        }
    
        public function boot(Container $app)
        {
        }
    }
    src/Util/000077500000000000000000000000001516067327100125725ustar00rootroot00000000000000src/Util/Repository.php000066400000000000000000000154521516067327100154710ustar00rootroot00000000000000 'php',
            'c' => 'clike',
            'h' => 'clike',
            'cpp' => 'clike',
            'm' => 'clike',
            'mm' => 'clike',
            'ino' => 'clike',
            'cs' => 'text/x-csharp',
            'java' => 'text/x-java',
            'clj' => 'clojure',
            'coffee' => 'coffeescript',
            'css' => 'css',
            'diff' => 'diff',
            'ecl' => 'ecl',
            'el' => 'erlang',
            'go' => 'go',
            'groovy' => 'groovy',
            'hbs' => 'handlebars',
            'hs' => 'haskell',
            'lhs' => 'haskell',
            'jsp' => 'application/x-jsp',
            'asp' => 'htmlembedded',
            'aspx' => 'htmlembedded',
            'html' => 'htmlmixed',
            'tpl' => 'htmlmixed',
            'js' => 'javascript',
            'json' => 'javascript',
            'jsx' => 'jsx',
            'less' => 'css',
            'lua' => 'lua',
            'md' => 'markdown',
            'markdown' => 'markdown',
            'sql' => 'sql',
            'swift' => 'swift',
            'twig' => 'twig',
            'ml' => 'ocaml',
            'mli' => 'ocaml',
            'pl' => 'perl',
            'pm' => 'perl',
            'pas' => 'pascal',
            'ps1' => 'powershell',
            'ini' => 'properties',
            'cfg' => 'properties',
            'nt' => 'ntriples',
            'py' => 'python',
            'rb' => 'ruby',
            'rst' => 'rst',
            'r' => 'r',
            'lock' => 'javascript',
            'sh' => 'shell',
            'ss' => 'scheme',
            'scala' => 'text/x-scala',
            'scm' => 'scheme',
            'sls' => 'scheme',
            'sps' => 'scheme',
            'rs' => 'rust',
            'st' => 'smalltalk',
            'tex' => 'stex',
            'vbs' => 'vbscript',
            'vb' => 'vbscript',
            'v' => 'verilog',
            'xml' => 'xml',
            'xsd' => 'xml',
            'xsl' => 'xml',
            'xul' => 'xml',
            'xlf' => 'xml',
            'xliff' => 'xml',
            'xaml' => 'xml',
            'wxs' => 'xml',
            'wxl' => 'xml',
            'wxi' => 'xml',
            'wsdl' => 'xml',
            'svg' => 'xml',
            'rss' => 'xml',
            'rdf' => 'xml',
            'plist' => 'xml',
            'mxml' => 'xml',
            'kml' => 'xml',
            'glade' => 'xml',
            'xq' => 'xquery',
            'xqm' => 'xquery',
            'xquery' => 'xquery',
            'xqy' => 'xquery',
            'yml' => 'yaml',
            'yaml' => 'yaml',
            'png' => 'image',
            'jpg' => 'image',
            'gif' => 'image',
            'jpeg' => 'image',
            'bmp' => 'image',
            'csproj' => 'xml',
            'iml' => 'xml',
        ];
    
        protected static $binaryTypes = [
            'exe', 'com', 'so', 'la', 'o', 'dll', 'pyc',
            'jpg', 'jpeg', 'bmp', 'gif', 'png', 'xmp', 'pcx', 'svgz', 'ttf', 'tiff', 'oet',
            'gz', 'tar', 'rar', 'zip', '7z', 'jar', 'class',
            'odt', 'ods', 'pdf', 'doc', 'docx', 'dot', 'xls', 'xlsx',
        ];
    
        public function __construct(Application $app)
        {
            $this->app = $app;
        }
    
        /**
         * Returns the file type based on filename by treating the extension.
         *
         * The file type is used by CodeMirror, a Javascript-based IDE implemented in
         * GitList, to properly highlight the blob syntax (if it's a source-code)
         *
         * @param  string $file File name
         *
         * @return mixed  File type
         */
        public function getFileType($file)
        {
            if ($file === 'Dockerfile') {
                return 'dockerfile';
            };
    
            if (($pos = strrpos($file, '.')) !== false) {
                $fileType = substr($file, $pos + 1);
            } else {
                return 'text';
            }
    
            if (!empty($this->app['filetypes'])) {
                if (isset($this->app['filetypes'][$fileType])) {
                    return $this->app['filetypes'][$fileType];
                }
            }
    
            if (isset($this->defaultFileTypes[$fileType])) {
                return $this->defaultFileTypes[$fileType];
            }
    
            return 'text';
        }
    
        /**
         * Returns whether the file is binary.
         *
         * @param string $file
         *
         * @return bool
         */
        public function isBinary($file)
        {
            if (($pos = strrpos($file, '.')) !== false) {
                $fileType = substr($file, $pos + 1);
            } else {
                return false;
            }
    
            if (!empty($this->app['binary_filetypes']) && array_key_exists($fileType, $this->app['binary_filetypes'])) {
                return $this->app['binary_filetypes'][$fileType];
            }
    
            if (in_array($fileType, self::$binaryTypes)) {
                return true;
            }
    
            return false;
        }
    
        public function getReadme($repository, $branch = null, $path = '')
        {
            if ($branch === null) {
                $branch = $repository->getHead();
            }
    
            if ($path != '') {
                $path = "$path/";
            }
    
            $files = $repository->getTree($path != '' ? "$branch:\"$path\"" : $branch)->output();
    
            foreach ($files as $file) {
                if (preg_match('/^readme*/i', $file['name'])) {
                    return [
                        'filename' => $file['name'],
                        'content' => $repository->getBlob("$branch:\"$path{$file['name']}\"")->output(),
                    ];
                }
            }
            // No contextual readme, try to catch the main one if we are in deeper context
            if ($path != '') {
                return $this->getReadme($repository, $branch, '');
            }
    
            return [];
        }
    
        /**
         * Returns an Array where the first value is the tree-ish and the second is the path.
         *
         * @param  \GitList\Git\Repository $repository
         * @param  string                  $branch
         * @param  string                  $tree
         *
         * @return array
         */
        public function extractRef($repository, $branch = '', $tree = '')
        {
            $branch = trim($branch, '/');
            $tree = trim($tree, '/');
            $input = $branch . '/' . $tree;
    
            // If the ref appears to be a SHA, just split the string
            if (preg_match('/^([[:alnum:]]{40})(.+)/', $input, $matches)) {
                $branch = $matches[1];
            } else {
                // Otherwise, attempt to detect the ref using a list of the project's branches and tags
                $validRefs = array_merge((array) $repository->getBranches(), (array) $repository->getTags());
                foreach ($validRefs as $key => $ref) {
                    if (!preg_match(sprintf('#^%s/#', preg_quote($ref, '#')), $input)) {
                        unset($validRefs[$key]);
                    }
                }
    
                // No exact ref match, so just try our best
                if (count($validRefs) > 1) {
                    preg_match('/([^\/]+)(.*)/', $input, $matches);
                    $branch = preg_replace('/^\/|\/$/', '', $matches[1]);
                } else {
                    // Extract branch name
                    $branch = array_shift($validRefs);
                }
            }
    
            return [$branch, $tree];
        }
    }src/Util/Routing.php000066400000000000000000000114771516067327100147440ustar00rootroot00000000000000app = $app;
        }
    
        /* @brief Return $commitish, $path parsed from $commitishPath, based on
         * what's in $repo. Raise a 404 if $branchpath does not represent a
         * valid branch and path.
         *
         * A helper for parsing routes that use commit-ish names and paths
         * separated by /, since route regexes are not enough to get that right.
         *
         * @param string $commitishPath
         * @param string $repo
         * @return array
         */
        public function parseCommitishPathParam($commitishPath, $repo)
        {
            $app = $this->app;
            $repository = $app['git']->getRepositoryFromName($app['git.repos'], $repo);
    
            $commitish = null;
            $path = null;
    
            $slashPosition = strpos($commitishPath, '/');
            if (strlen($commitishPath) >= 40 &&
                ($slashPosition === false ||
                 $slashPosition === 40)) {
                // We may have a commit hash as our commitish.
                $hash = substr($commitishPath, 0, 40);
                if (preg_match('/[^a-zA-Z0-9]/i', $hash) === 0) {
                    if ($repository->hasCommit($hash)) {
                        $commitish = $hash;
                    }
                }
            }
    
            if ($commitish === null) {
                $branches = $repository->getBranches();
    
                $tags = $repository->getTags();
                if ($tags !== null && count($tags) > 0) {
                    $branches = array_merge($branches, $tags);
                }
    
                $matchedBranch = null;
                $matchedBranchLength = 0;
                foreach ($branches as $branch) {
                    if (strpos($commitishPath, $branch) === 0 &&
                        strlen($branch) > $matchedBranchLength) {
                        $matchedBranch = $branch;
                        $matchedBranchLength = strlen($matchedBranch);
                    }
                }
    
                if ($matchedBranch !== null) {
                    $commitish = $matchedBranch;
                } else {
                    // We may have partial commit hash as our commitish.
                    $hash = $slashPosition === false ? $commitishPath : substr($commitishPath, 0, $slashPosition);
                    if ($repository->hasCommit($hash)) {
                        $commit = $repository->getCommit($hash);
                        $commitish = $commit->getHash();
                    } else {
                        throw new EmptyRepositoryException('This repository is currently empty. There are no commits.');
                    }
                }
            }
    
            $commitishLength = strlen($commitish);
            $path = substr($commitishPath, $commitishLength);
            if (strpos($path, '/') === 0) {
                $path = substr($path, 1);
            }
    
            return array($commitish, $path);
        }
    
        public function getBranchRegex()
        {
            static $branchRegex = null;
    
            if ($branchRegex === null) {
                $branchRegex = '(?!/|.*([/.]\.|//|@\{|\\\\))[^\040\177 ~^:?*\[]+(?app['git']->getRepositories($this->app['git.repos'])
                );
                usort(
                    $quotedPaths,
                    function ($a, $b) {
                        return strlen($b) - strlen($a);
                    }
                );
                $regex = implode('|', $quotedPaths);
            }
            return $regex;
        }
    
        public function isWindows()
        {
            switch (PHP_OS) {
                case 'WIN32':
                case 'WINNT':
                case 'Windows':
                    return true;
                default:
                    return false;
            }
        }
    
        /**
         * Strips the base path from a full repository path
         *
         * @param  string $repoPath Full path to the repository
         * @return string Relative path to the repository from git.repositories
         */
        public function getRelativePath($repoPath)
        {
            if (strpos($repoPath, $this->app['git.repos']) === 0) {
                $relativePath = substr($repoPath, strlen($this->app['git.repos']));
    
                return ltrim(strtr($relativePath, '\\', '/'), '/');
            } else {
                throw new \InvalidArgumentException(
                    sprintf("Path '%s' does not match configured repository directory", $repoPath)
                );
            }
        }
    }
    
    src/Util/View.php000066400000000000000000000024071516067327100142200ustar00rootroot00000000000000 $path) {
                $breadcrumbs[] = array(
                    'dir'  => $path,
                    'path' => implode('/', array_slice($paths, 0, $i + 1)),
                );
            }
    
            return $breadcrumbs;
        }
    
        public function getPager($pageNumber, $totalCommits)
        {
            $pageNumber = (empty($pageNumber)) ? 0 : $pageNumber;
            $lastPage = intval($totalCommits / 15);
    
            // If total commits are integral multiple of 15, the lastPage will be commits/15 - 1.
            $lastPage = ($lastPage * 15 == $totalCommits) ? $lastPage - 1 : $lastPage;
            $nextPage = $pageNumber + 1;
            $previousPage = $pageNumber - 1;
    
            return array('current' => $pageNumber,
                         'next' => $nextPage,
                         'previous' => $previousPage,
                         'last' => $lastPage,
                         'total' => $totalCommits,
            );
        }
    }
    src/css-postfix000066400000000000000000000001001516067327100140510ustar00rootroot0000000000000070d464b5072e216915595192980aeb66414879b74b8abf06c30347c6ce498380tests/000077500000000000000000000000001516067327100122305ustar00rootroot00000000000000tests/RepositoryTest.php000066400000000000000000000017061516067327100157640ustar00rootroot00000000000000prophesize(Client::class);
            $client->run(Argument::type(Repository::class), "grep -i --line-number -- '=sleep 5;' master")->shouldBeCalled();
    
            $repository = new Repository('/tmp', $client->reveal());
            $repository->searchTree('--open-files-in-pager=sleep 5;', 'master');
            $repository->searchTree('-O=sleep 5;', 'master');
        }
    
        public function testIsSanitizingSearchWithAnyOption()
        {
            $client = $this->prophesize(Client::class);
            $client->run(Argument::type(Repository::class), "grep -i --line-number -- 'foobar  =bar;' foo")->shouldBeCalled();
    
            $repository = new Repository('/tmp', $client->reveal());
            $repository->searchTree('foobar --bar --foo=bar;', 'foo');
        }
    }twig/000077500000000000000000000000001516067327100120405ustar00rootroot00000000000000twig/blame.twig000066400000000000000000000020041516067327100140100ustar00rootroot00000000000000{% extends 'layout_page.twig' %}
    
    {% set page = 'commits' %}
    
    {% block title %}P3X GitList{% endblock %}
    
    {% block content %}
        {% embed 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Blame', path:''}, {dir: file, path:''}]} %}
    
            {% block left %}
                {% if blames %}
                    
                {% endif %}
            {%  endblock %}
    
        {% endembed %}
        {% if blames %}
    
            {% for blame in blames %}
                
    {{ blame.line }}
    {% endfor %} {% else %}

    The blames.

    {% endif %} {% endblock %} twig/breadcrumb.twig000066400000000000000000000075211516067327100150470ustar00rootroot00000000000000
     RSS  ZIP  TAR {% if app.show_http_remote or app.show_ssh_remote %}  Clone {% endif %} {% block right %}{% endblock %}
    {% block left %}{% endblock %} {% if app.show_http_remote or app.show_ssh_remote %} {% endif %}
    twig/browser.twig000066400000000000000000000040671516067327100144260ustar00rootroot00000000000000 twig/commit.twig000066400000000000000000000076051516067327100142340ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'commits' %} {% block title %}P3X GitList{% endblock %} {% block content %}

    Loading a big commit ...
    {% embed 'breadcrumb.twig' with {breadcrumbs: [{dir: "Commit #{commit.hash}", path:''}]} %} {% block right %} Browse code {% endblock %} {% endembed %}

    {{ commit.message }} {% if commit.body is not empty %} {{ commit.body | nl2br }} {% endif %}

    {{ commit.author.name }} authored on {{ commit.date | format_date }} {% if commit.author.email != commit.commiter.email %} • {{ commit.commiter.name }} committed on {{ commit.commiterDate | format_date }} {% endif %}
    Showing {{ commit.changedFiles }} changed files
    {% for diff in commit.diffs %} {{ diff.file }}
    Click to load this diff ...
    {% endfor %} {% endblock %} twig/commits-list.twig000066400000000000000000000043731516067327100153670ustar00rootroot00000000000000{% if commits %} {% for date, commit in commits %} {% for item in commit %} {% endfor %}
    {{ date | date("F j, Y") }}
     Browse  Changes

    {{ item.message }}

    {{ item.author.name }} authored on {{ item.date | format_date }} {% if item.author.email != item.commiter.email %} • {{ item.commiter.name }} committed on {{ item.commiterDate | format_date }} {% endif %}
    {% endfor %} {% else %}

    No more commits.

    {% endif %} {% if page != 'searchcommits' %} {% endif %} twig/commits.twig000066400000000000000000000004201516067327100144030ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'commits' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% include 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Commit history', path:''}]} %} {% include 'commits-list.twig' %} {% endblock %} twig/error.twig000066400000000000000000000006441516067327100140710ustar00rootroot00000000000000{% extends 'layout.twig' %} {% block title %}P3X GitList{% endblock %} {% block body %} {% include 'navigation.twig' %}
    Oops! {{ message }}
    You may go back to previous page. {% include 'footer.twig' %}
    {% endblock %} twig/file.twig000066400000000000000000000174701516067327100136640ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'files' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% embed 'breadcrumb.twig' with {breadcrumbs: breadcrumbs} %} {% block right %} {% if (fileType != 'image' and fileType != 'markdown') or (enforceCodemirror) %} {% elseif fileType == 'markdown' %} Edit {% endif %} {% endblock %} {% block left %}
    Raw Blame History {% if (fileType != 'image' and fileType != 'markdown') or enforceCodemirror %} {% endif %} {% if fileType == 'markdown' %} {% if enforceCodemirror %} Markdown rendered {% else %} Markdown code {% endif %} {% endif %}
    {% endblock %} {% endembed %}
    {% if fileType == 'image' %}
    {{ file }}
    {% elseif fileType == 'markdown' and enforceCodemirror != true %} {% include 'markdown.twig' with {'filename': file, 'data': blob} %} {% else %}
    {{ blob|htmlentities|raw }}
    {% endif %}
    {% endblock %} twig/footer.twig000066400000000000000000000002441516067327100142320ustar00rootroot00000000000000 twig/index.twig000066400000000000000000000035001516067327100140410ustar00rootroot00000000000000{% extends 'layout.twig' %} {% block title %}P3X GitList{% endblock %} {% block body %} {% include 'navigation.twig' %}
    {% for repository in repositories %}
    {{ repository.name | remove_extension }}
    {% if repository.description %} {{ repository.description }} {% else %} There is no repository description file. Please, create one to remove this message. {% endif %}
    {% endfor %}
    {% include 'footer.twig' %}
    {% endblock %} twig/layout.tpl.twig000066400000000000000000000024471516067327100150560ustar00rootroot00000000000000 {% block title %}Welcome!{% endblock %} {% block body %}{% endblock %} {% block javascripts %} {% endblock %} twig/layout_page.twig000066400000000000000000000037611516067327100152540ustar00rootroot00000000000000{% extends 'layout.twig' %} {% block body %} {% include 'navigation.twig' %}
    {% if page in ['commits', 'searchcommits'] %}
    {% else %}
    {% endif %} {% include 'menu.twig' %} {% block content %}{% endblock %}
    {% include 'footer.twig' %} {% endblock %} twig/markdown.twig000066400000000000000000000003111516067327100145510ustar00rootroot00000000000000
      {{ filename }}
    {{ data }}
    twig/menu.twig000066400000000000000000000016261516067327100137050ustar00rootroot00000000000000 twig/navigation.twig000066400000000000000000000031001516067327100150650ustar00rootroot00000000000000
    twig/network.twig000066400000000000000000000007621516067327100144320ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'network' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% include 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Network Graph ', path: ''}, {dir: commitishPath, path: ''}]} %}
    {#
    #}
    {% endblock %} twig/rss.twig000066400000000000000000000013621516067327100135450ustar00rootroot00000000000000 Latest commits in {{ repo }}:{{ branch }} RSS provided by GitList {{ url('homepage') }} {% for commit in commits %} {{ commit.message }} {{ commit.author.name }} authored {{ commit.shortHash }} in {{ commit.date | format_date }} {{ url('commit', {repo: repo, commit: commit.hash}) }} {{ commit.date | date('r') }} {{ commit.author.email }} ({{ commit.author.name }}) {% endfor %} twig/search.twig000066400000000000000000000021321516067327100141770ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'files' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% embed 'breadcrumb.twig' with {breadcrumbs: breadcrumbs} %} {% block left %} {% if results %} {% endif %} {% endblock %} {% endembed %} {% if results %} {% for result in results %}
    {{ result.match }}
    {% endfor %} {% else %}

    The search found no result.

    {% endif %} {% endblock %} twig/searchcommits.twig000066400000000000000000000010331516067327100155720ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'searchcommits' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% embed 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Commits search results for: ' ~ query, path:''}]} %} {% block left %} {% if commits %} {% endif %} {% endblock %} {% endembed %} {% include 'commits-list.twig' %} {% endblock %} twig/stats.twig000066400000000000000000000055471516067327100141050ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'stats' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% include 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Statistics', path:''}, {dir: branch, path:''}]} %}
      File extensions {{ stats.extensions|length }}
      {% for ext, amount in stats.extensions %}
    • {{ ext }} {{ amount }}
    • {% endfor %}
    {{ authors|length }}   Authors
      Stats
    • {{ stats.files }} Total files
    • {{ stats.size }} bytes {{ stats.size | format_size }}
    {% endblock %} twig/tree.twig000066400000000000000000000061321516067327100136750ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'files' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% embed 'breadcrumb.twig' with {breadcrumbs: breadcrumbs } %} {% block right %} {% endblock %} {% endembed %} {% if files is not empty %} {% if parent is not null %} {% endif %} {% for file in files %} {% endfor %}
    Name Mode Size
    {% if not parent %} .. {% else %} .. {% endif %}
    {%- if file.type == "folder" or file.type == "symlink" -%}   {{ file.name }} {%- elseif file.type == "module" -%}   {{ file.name }} @ {{ file.shortHash }} {%- else -%}   {{ file.name }} {%- endif -%} {{ file.mode }} {% if file.size %}{{ (file.size / 1024) | number_format }} kb{% endif %}
    {% else %}

    This repository is empty.

    {% endif %} {% if readme is defined and readme is not empty %} {% include 'markdown.twig' with {'filename': readme.filename, 'data': readme.content} %} {% endif %} {% endblock %} twig/treegraph.twig000066400000000000000000000033361516067327100147220ustar00rootroot00000000000000{% extends 'layout_page.twig' %} {% set page = 'treegraph' %} {% block title %}P3X GitList{% endblock %} {% block content %} {% include 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Graph', path:''}]} %}
      {% for item in graphItems %}
    • {{ item.relation }}
    • {% endfor %}
      {% for item in graphItems %}
    • {% if item.rev is defined %} {{ item.short_rev }} {{ item.branch }} {{ item.subject }} by {{ item.author }} on {{ item.date | date(gitlist_date_format) }} {% else %} {% endif %}
    • {% endfor %}
    {% endblock %} webpack.config.js000066400000000000000000000133371516067327100143130ustar00rootroot00000000000000const fs = require('fs').promises const path = require('path'); const webpack = require('webpack'); const utils = require('corifeus-utils') const ExtractTextPlugin = require('extract-text-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const WebpackOnBuildPlugin = require('on-build-webpack'); const fileAsset = `[name].[hash].[ext]`; const minimize = process.argv.includes('--production'); const mode = minimize ? 'development' : 'production'; let minimizer = undefined; const buildDir = __dirname + '/public/webpack'; let devtool; const plugins = [ new ExtractTextPlugin({ filename: '[name].[hash].css', disable: false, allChunks: true }), new HtmlWebpackPlugin({ template: `${__dirname}/twig/layout.tpl.twig`, inject: 'head', chunksSortMode: 'dependency', chunks: ['bundle'], filename: `${__dirname}/twig/layout.twig`, }), ]; plugins.push( new WebpackOnBuildPlugin(async (stats) => { try { const newFileNames = Object.keys(stats.compilation.assets).map(file => path.resolve(`${buildDir}/${file}`)); const baseDir = path.resolve(buildDir); const baseDirList = await utils.fs.readdirRecursive(baseDir) const promises = []; for(let baseDirFile of baseDirList) { if (!newFileNames.includes(baseDirFile)) { promises.push( fs.unlink(baseDirFile) ) } } await Promise.all(promises); } catch(e) { console.error(e) process.exit(-1) } }), ) if (minimize) { devtool = false; const bannerText = require('corifeus-builder').utils.license(); minimizer = [ new UglifyJsPlugin({ sourceMap: true, parallel: true, cache: true, extractComments: { condition: /^\**!|@preserve|@license|@cc_on/, file: function (fileName) { return `${fileName}.LICENSE.txt`; }, banner: function (webpackBanner) { return ` ${bannerText} For more information about all licenses, please see ${webpackBanner} `; } }, uglifyOptions: { compress: { warnings: false }, ecma: 8, // todo found out if mangle use or not // mangle: false === keep function names // mangle: true === drop function names mangle: false, sourceMap: true, comments: false, beautify: false }, }), ] plugins.push( new webpack.BannerPlugin({ banner: bannerText, include: /\.css$/, exclude: /\.ts$|\.js$/, // hash:[hash], chunkhash:[chunkhash], name:[name], filebase:[filebase], query:[query], file:[file] }) ) plugins.push( new webpack.SourceMapDevToolPlugin({ filename: 'sourcemaps/[file].map', append: '\n//# sourceMappingURL=/[url]' }) ) } const fileLoader = [ { loader: 'file-loader', options: { name: fileAsset, outputPath: 'assets', context: 'assets', // publicPath: 'webpack/assets', // useRelativePath: true, } } ] module.exports = { // watch: true, devtool: devtool, entry: { bundle: "./public/js/bundle.js", }, output: { path: buildDir, filename: '[name].[hash].js', chunkFilename: '[id].[hash].chunk.js', // publicPath: '{{ app.url_subdir }}/webpack/', publicPath: './webpack/', }, module: { rules: [ { test: /\.less$/, use: [{ loader: 'style-loader' // creates style nodes from JS strings }, { loader: 'css-loader' // translates CSS into CommonJS }, { loader: 'less-loader' // compiles Less to CSS }], }, { test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: mode, caseSensitive: true } }] }, { test: /\.(png|jpe?g|gif|ico)$/, use: fileLoader }, { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, use: fileLoader }, { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, use: fileLoader }, { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, use: fileLoader }, { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: fileLoader }, { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: fileLoader }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [ { loader: 'css-loader', options: { minimize: minimize, sourceMap: true }, }] }) } ] }, optimization: { minimize: minimize, minimizer: minimizer }, plugins: plugins, mode: mode, }