Compare commits
107 commits
Author | SHA1 | Date | |
---|---|---|---|
Simon Vieille | c9fee1ea42 | ||
Simon Vieille | 196da8cb45 | ||
Simon Vieille | cb286ce704 | ||
Simon Vieille | 6d84cf319c | ||
Simon Vieille | e5f996705e | ||
Simon Vieille | 7c32234626 | ||
Simon Vieille | 7195609086 | ||
Simon Vieille | 3972513905 | ||
Simon Vieille | 0ff9d4a526 | ||
Simon Vieille | a8a3eadc71 | ||
Simon Vieille | f2e30bbd8f | ||
Simon Vieille | faab3c4252 | ||
Simon Vieille | f6136404c9 | ||
Simon Vieille | 426cf0e1f1 | ||
Simon Vieille | d67ac40e3d | ||
Simon Vieille | 4ee4311c1a | ||
Simon Vieille | 9eb8a73462 | ||
Simon Vieille | 7f77b92554 | ||
Simon Vieille | 0eb689b5dc | ||
Simon Vieille | 971812f2d8 | ||
Simon Vieille | fbac488f62 | ||
Simon Vieille | f36783b2ce | ||
Simon Vieille | 001901a8f7 | ||
Simon Vieille | 6e848f0982 | ||
Simon Vieille | b43baac802 | ||
Simon Vieille | 2ac9737409 | ||
Simon Vieille | b7e6d8c69c | ||
Simon Vieille | 2d8f19437a | ||
Simon Vieille | af30221295 | ||
Simon Vieille | 999b4a25a7 | ||
Simon Vieille | 32f01bcd75 | ||
Simon Vieille | 3b812523a9 | ||
Simon Vieille | 418d150833 | ||
Simon Vieille | 9059fe214b | ||
Simon Vieille | abed0e4b3c | ||
Simon Vieille | 8caff598e8 | ||
Simon Vieille | 6c12f92fd1 | ||
Simon Vieille | 301fca186d | ||
Simon Vieille | ff4a592203 | ||
Simon Vieille | 2b4625c9b4 | ||
Simon Vieille | b25809bda6 | ||
Simon Vieille | 41d1770dc2 | ||
Simon Vieille | 851dbd282b | ||
Simon Vieille | e30571c6b7 | ||
Simon Vieille | 31ffaced48 | ||
Simon Vieille | acf48c4a75 | ||
Simon Vieille | 2584014d78 | ||
Simon Vieille | e74a87a131 | ||
Simon Vieille | b77c4800c2 | ||
Simon Vieille | a0e305117c | ||
Simon Vieille | d73e4df326 | ||
Simon Vieille | b74960ecd3 | ||
Simon Vieille | ebc0ea2bf8 | ||
Simon Vieille | 3a78e500df | ||
Simon Vieille | db8b512670 | ||
Simon Vieille | 411447ae3e | ||
Simon Vieille | d56c33c29f | ||
Simon Vieille | 37751f51a6 | ||
Simon Vieille | b83e1655b5 | ||
Simon Vieille | 1a79e4520f | ||
Simon Vieille | 21a85c0db4 | ||
Simon Vieille | 88ce6d66db | ||
Simon Vieille | 43fd509d69 | ||
Simon Vieille | d441d7e834 | ||
Simon Vieille | 9fe6510fc9 | ||
Simon Vieille | 4d2cf30de1 | ||
Simon Vieille | ab58bdb82d | ||
Simon Vieille | 87348c8335 | ||
Simon Vieille | f6e4837776 | ||
Simon Vieille | a478fb3de5 | ||
Simon Vieille | 91cdb2341c | ||
Simon Vieille | ffe3540565 | ||
Simon Vieille | 80b3c0bbdb | ||
Simon Vieille | a9435906fe | ||
Simon Vieille | 7a3ea9d060 | ||
Simon Vieille | 99635e8e3c | ||
Simon Vieille | 50025705d1 | ||
Simon Vieille | c46cf0fdb7 | ||
Simon Vieille | 79ba41a983 | ||
Simon Vieille | 8a7de8a107 | ||
Simon Vieille | bc67a2ce1c | ||
Simon Vieille | 0f127a0920 | ||
Simon Vieille | 834faedc1f | ||
Simon Vieille | 1898c31e21 | ||
Simon Vieille | fb2d387fef | ||
Simon Vieille | 0060b18842 | ||
Showfom | 3d1a6f8158 | ||
Simon Vieille | 1c52988222 | ||
Simon Vieille | 3fcdae9270 | ||
Simon Vieille | 2f1d57d36b | ||
Simon Vieille | 0b6c4d7ac1 | ||
Simon Vieille | 4a035ba7ed | ||
Simon Vieille | 706823c04a | ||
Simon Vieille | 87bd9e9db5 | ||
Simon Vieille | 48eacc5cb8 | ||
Simon Vieille | df86035225 | ||
Simon Vieille | 43db48a715 | ||
Simon Vieille | c7a03c4bf9 | ||
Simon Vieille | 61b071feb8 | ||
Simon Vieille | 36f4fb98ff | ||
Simon Vieille | 9dfbde6730 | ||
Simon Vieille | 74b23a59b5 | ||
Simon Vieille | 2702a1d987 | ||
Simon Vieille | 221e28832f | ||
Simon Vieille | ab47699731 | ||
Simon Vieille | eb1f4f1df3 | ||
Simon Vieille | 0e02add6e6 |
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -2,11 +2,13 @@
|
||||||
/.mage/logs/*.log
|
/.mage/logs/*.log
|
||||||
/composer.lock
|
/composer.lock
|
||||||
/vendor/
|
/vendor/
|
||||||
/propel.yml
|
/propel.yaml
|
||||||
/src/Gist/Model/Base/
|
/src/Gist/Model/Base/
|
||||||
/src/Gist/Model/Map/
|
/src/Gist/Model/Map/
|
||||||
/web/components/
|
|
||||||
/app/propel/
|
/app/propel/
|
||||||
|
/node_modules/
|
||||||
|
/app/config/config.yml
|
||||||
/app/config/propel/
|
/app/config/propel/
|
||||||
/data/
|
/data/
|
||||||
/trans/
|
/trans/
|
||||||
|
/cache/
|
||||||
|
|
0
.mage/config/environment/.gitignore
vendored
0
.mage/config/environment/.gitignore
vendored
|
@ -1,27 +0,0 @@
|
||||||
# prod
|
|
||||||
# Rename this file to "prod.yml"
|
|
||||||
deployment:
|
|
||||||
user: gist
|
|
||||||
from: ./
|
|
||||||
to: /var/www/gist/
|
|
||||||
excludes:
|
|
||||||
- "*.svn"
|
|
||||||
- "*.git"
|
|
||||||
- "*.swp"
|
|
||||||
- "app/config/propel/"
|
|
||||||
- "app/propel/"
|
|
||||||
- "data/git"
|
|
||||||
- "deploy"
|
|
||||||
- "tags"
|
|
||||||
- "propel.yaml"
|
|
||||||
- "composer.lock"
|
|
||||||
- "composer.json"
|
|
||||||
- "bower.json"
|
|
||||||
- ".bowerrc"
|
|
||||||
hosts:
|
|
||||||
- gist.mycompany.com
|
|
||||||
tasks:
|
|
||||||
pre-deploy:
|
|
||||||
on-deploy:
|
|
||||||
post-deploy:
|
|
||||||
verbose_logging: true
|
|
|
@ -1,7 +0,0 @@
|
||||||
# global settings
|
|
||||||
name: Gist
|
|
||||||
email:
|
|
||||||
notifications: false
|
|
||||||
logging: true
|
|
||||||
maxlogs: 30
|
|
||||||
ssh_needs_tty: false
|
|
2
.mage/logs/.gitignore
vendored
2
.mage/logs/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
0
.mage/tasks/.gitignore
vendored
0
.mage/tasks/.gitignore
vendored
26
ISSUE_TEMPLATE.md
Normal file
26
ISSUE_TEMPLATE.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
* GIST version or GIT commit: ...
|
||||||
|
* PHP Version: ...
|
||||||
|
* GIT version. ...
|
||||||
|
* HTTPD (Nginx, Apache2): ...
|
||||||
|
* DBMS (MySQL, SQLite, PostgreSQL): ...
|
||||||
|
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
|
||||||
|
1. ...
|
||||||
|
2. ...
|
||||||
|
3. ...
|
||||||
|
|
||||||
|
#### Observed Results
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
#### Expected Results
|
||||||
|
|
||||||
|
...
|
45
Makefile
45
Makefile
|
@ -1,47 +1,52 @@
|
||||||
COMPOSER ?= composer
|
COMPOSER ?= composer
|
||||||
BOWER ?= bower
|
NPM ?= npm
|
||||||
GIT ?= git
|
GIT ?= git
|
||||||
MKDIR ?= mkdir
|
MKDIR ?= mkdir
|
||||||
PHP ?= php
|
PHP ?= php
|
||||||
|
RM ?= rm
|
||||||
|
|
||||||
all: update
|
all: update clean-cache
|
||||||
|
|
||||||
composer:
|
composer:
|
||||||
@echo "Installing application's dependencies"
|
@echo "Installing PHP dependencies"
|
||||||
@echo "-------------------------------------"
|
@echo "---------------------------"
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
$(COMPOSER) install $(COMPOSER_INSTALL_FLAGS)
|
${COMPOSER} install
|
||||||
bower:
|
|
||||||
@echo "Installing application's dependencies"
|
npm:
|
||||||
@echo "-------------------------------------"
|
@echo "Installing CSS/JS dependencies"
|
||||||
|
@echo "------------------------------"
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
$(BOWER) install
|
${NPM} install
|
||||||
|
${NPM} update
|
||||||
optimize:
|
|
||||||
@echo "Optimizing Composer's autoloader, can take some time"
|
|
||||||
@echo "----------------------------------------------------"
|
|
||||||
@echo
|
|
||||||
|
|
||||||
$(COMPOSER) dump-autoload --optimize
|
|
||||||
|
|
||||||
update:
|
update:
|
||||||
@echo "Updating application's dependencies"
|
@echo "Updating application's dependencies"
|
||||||
@echo "-----------------------------------"
|
@echo "-----------------------------------"
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
$(GIT) pull origin master
|
${GIT} pull origin master
|
||||||
${MKDIR} -p data/git
|
${MKDIR} -p data/git
|
||||||
$(COMPOSER) update
|
${MKDIR} -p data/cache
|
||||||
$(BOWER) install
|
${COMPOSER} update
|
||||||
|
${NPM} install
|
||||||
|
${NPM} update
|
||||||
|
|
||||||
|
clean-cache:
|
||||||
|
@echo "Removing cache"
|
||||||
|
@echo "--------------"
|
||||||
|
@echo
|
||||||
|
|
||||||
|
${RM} -fr cache/*
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@echo "Run development server"
|
@echo "Run development server"
|
||||||
@echo "----------------------"
|
@echo "----------------------"
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
$(PHP) -S 127.0.0.1:8080 -t web
|
${PHP} -S 127.0.0.1:8080 -t web
|
||||||
|
|
||||||
propel:
|
propel:
|
||||||
@echo "Propel migration"
|
@echo "Propel migration"
|
||||||
|
|
298
README.md
298
README.md
|
@ -1,303 +1,23 @@
|
||||||
Table of Contents
|
|
||||||
=================
|
|
||||||
|
|
||||||
* [GIST](#gist)
|
|
||||||
* [Requirements](#requirements)
|
|
||||||
* [Git](#git)
|
|
||||||
* [Composer](#composer)
|
|
||||||
* [Bower](#bower)
|
|
||||||
* [Installation](#installation)
|
|
||||||
* [Upgrade](#upgrade)
|
|
||||||
* [Makefile](#makefile)
|
|
||||||
* [API](#api)
|
|
||||||
* [Create a new gist](#create-a-new-gist)
|
|
||||||
* [Update an existing Gist](#update-an-existing-gist)
|
|
||||||
* [Console](#console)
|
|
||||||
* [Create and update gists](#create-and-update-gists)
|
|
||||||
* [Create user](#create-user)
|
|
||||||
* [Show stats](#show-stats)
|
|
||||||
* [Configuration](#configuration)
|
|
||||||
* [API](#api-1)
|
|
||||||
* [Authentication](#authentication)
|
|
||||||
* [Debug](#debug)
|
|
||||||
* [Deployment](#deployment)
|
|
||||||
* [Contributors](#contributors)
|
|
||||||
|
|
||||||
GIST
|
GIST
|
||||||
====
|
====
|
||||||
|
|
||||||
GIST is an open-source application to share code.
|
GIST is an open-source application to share code.
|
||||||
https://www.deblan.io/post/517/gist-est-dans-la-place
|
https://www.deblan.io/post/517/gist-est-dans-la-place
|
||||||
|
|
||||||
![Gist](https://upload.deblan.org/u/2015-11/565b93a5.png "Gist")
|
**[Read the wiki for more information](https://gitnet.fr/deblan/gist/wiki/_pages).**
|
||||||
|
|
||||||
![Gist](https://upload.deblan.org/u/2016-06/57655dec.png "Gist")
|
### Editor
|
||||||
|
|
||||||
Requirements
|
![Gist](https://upload.deblan.org/u/2018-08/5b7ab7a6.png "Gist editor")
|
||||||
------------
|
|
||||||
|
|
||||||
* PHP >= 5.4
|
### Result
|
||||||
* GIT
|
|
||||||
* MySQL, PostgreSQL or SQLite
|
|
||||||
* Composer (php)
|
|
||||||
* Bower (node)
|
|
||||||
|
|
||||||
### Git
|
![Gist](https://upload.deblan.org/u/2018-08/5b7ab7d4.png "Gist result")
|
||||||
|
|
||||||
Git can maybe be downloaded from your system's repositories.
|
### Account
|
||||||
|
|
||||||
$ git config --global user.email "you@example.com"
|
![Gist](https://upload.deblan.org/u/2018-08/5b7aba2d.png "Gist account")
|
||||||
$ git config --global user.name "Your Name"
|
|
||||||
|
|
||||||
### Composer
|
### Embeded Gist
|
||||||
|
|
||||||
Composer can maybe be downloaded from your system's repositories.
|
![Gist](https://upload.deblan.org/u/2018-08/5b7ab81c.png "Embeded Gist")
|
||||||
Else, follow the next instructions:
|
|
||||||
|
|
||||||
# With cURL
|
|
||||||
$ curl -sS https://getcomposer.org/installer | php
|
|
||||||
|
|
||||||
# With Wget
|
|
||||||
$ wget -O - -q https://getcomposer.org/installer | php
|
|
||||||
|
|
||||||
$ chmod +x composer.phar
|
|
||||||
|
|
||||||
# For a local installation and if the envvar PATH contains "$HOME/bin/"
|
|
||||||
$ mv composer.phar ~/bin/composer
|
|
||||||
|
|
||||||
# For a global installation
|
|
||||||
$ sudo mv composer.phar /usr/local/bin/composer
|
|
||||||
|
|
||||||
### Bower
|
|
||||||
|
|
||||||
$ sudo apt-get install npm
|
|
||||||
$ sudo npm install -g bower
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
$ cd /path/to/www/
|
|
||||||
$ git clone https://gitnet.fr/deblan/gist
|
|
||||||
$ cd gist
|
|
||||||
$ make
|
|
||||||
$ mv propel-dist.yaml propel.yaml
|
|
||||||
|
|
||||||
Edit `propel.yaml`. **Use spaces instead of tabulations**.
|
|
||||||
|
|
||||||
**MySQL**
|
|
||||||
|
|
||||||
propel:
|
|
||||||
database:
|
|
||||||
connections:
|
|
||||||
default:
|
|
||||||
adapter: mysql
|
|
||||||
# http://www.php.net/manual/en/ref.pdo-mysql.connection.php
|
|
||||||
dsn: "mysql:host=DATABASE_SERVER;dbname=DATABASE_NAME"
|
|
||||||
user: DATEBASE_USER
|
|
||||||
password: DATEBASE_PASSWORD
|
|
||||||
settings:
|
|
||||||
charset: utf8
|
|
||||||
queries:
|
|
||||||
utf8: "SET NAMES utf8 COLLATE utf8_unicode_ci, COLLATION_CONNECTION = utf8_unicode_ci, COLLATION_DATABASE = utf8_unicode_ci, COLLATION_SERVER = utf8_unicode_ci"
|
|
||||||
|
|
||||||
[...]
|
|
||||||
|
|
||||||
**SQLITE**
|
|
||||||
|
|
||||||
propel:
|
|
||||||
database:
|
|
||||||
connections:
|
|
||||||
default:
|
|
||||||
adapter: sqlite
|
|
||||||
# http://www.php.net/manual/en/ref.pdo-sqlite.connection.php
|
|
||||||
dsn: "sqlite:/PATH/TO/gist.sqlite"
|
|
||||||
user: ~
|
|
||||||
password: ~
|
|
||||||
|
|
||||||
[...]
|
|
||||||
|
|
||||||
Then `$ make propel`.
|
|
||||||
|
|
||||||
Edit `app/bootstrap.php.d/70-security.php` and modify the value of `$app['token']` with a strong secret phrase.
|
|
||||||
|
|
||||||
The web server must have permission to write into `data`.
|
|
||||||
|
|
||||||
$ sudo chown -R www-data:www-data data
|
|
||||||
|
|
||||||
Your webserver must be configured to serve `web/` as document root. If you use nginx, all virtual paths must be rooted with `web/index.php` or `web/app_dev.php` ([documentation](https://www.nginx.com/resources/wiki/start/topics/recipes/symfony/)). If you use apache, you must enable the `rewrite` module and restart:
|
|
||||||
|
|
||||||
$ sudo a2enmod rewrite
|
|
||||||
$ sudo service apache2 restart
|
|
||||||
|
|
||||||
Upgrade
|
|
||||||
-------
|
|
||||||
|
|
||||||
$ make update
|
|
||||||
$ make propel
|
|
||||||
|
|
||||||
Makefile
|
|
||||||
--------
|
|
||||||
|
|
||||||
A Makefile is provided to automate some tasks.
|
|
||||||
|
|
||||||
* `make` will install application's dependencies via Composer and Bower,
|
|
||||||
* `make optimize` will run Composer's autoloader dump script with classmap
|
|
||||||
* `make update` will update the application
|
|
||||||
* `make propel` will generate propel's files
|
|
||||||
* `make run` will run development server on http://127.0.0.1:8080/
|
|
||||||
|
|
||||||
API
|
|
||||||
---
|
|
||||||
|
|
||||||
### Create a new gist
|
|
||||||
|
|
||||||
**POST** /{locale}/api/create
|
|
||||||
Params:
|
|
||||||
|
|
||||||
* `form[title]`: String (required, can be empty)
|
|
||||||
* `form[type]`: String (required)
|
|
||||||
Values: html, css, javascript, php, sql, xml, yaml, perl, c, asp, python, bash, actionscript3, text
|
|
||||||
* `form[content]`: String (required)
|
|
||||||
|
|
||||||
**Responses:**
|
|
||||||
|
|
||||||
* Code `200`: A json which contains gist's information. Example:
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
"url": "https:\/\/gist.deblan.org\/en\/view\/55abcfa7771e0\/f4afbf72967dd95e3461490dcaa310d728d6a97d",
|
|
||||||
"gist": {
|
|
||||||
"Id": 66,
|
|
||||||
"Title": "test prod",
|
|
||||||
"Cipher": false,
|
|
||||||
"Type": "javascript",
|
|
||||||
"File": "55abcfa7771e0",
|
|
||||||
"CreatedAt": "2015-07-19T16:26:15Z",
|
|
||||||
"UpdatedAt": "2015-07-19T16:26:15Z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Code `405`: Method Not Allowed
|
|
||||||
* Code `400`: Bad Request
|
|
||||||
|
|
||||||
### Update an existing Gist
|
|
||||||
|
|
||||||
**POST** /{locale}/api/update/{id}
|
|
||||||
Params:
|
|
||||||
|
|
||||||
* `{id}`: Gist Id (required)
|
|
||||||
* `form[content]`: String (required)
|
|
||||||
|
|
||||||
**Responses:**
|
|
||||||
|
|
||||||
* Code `200`: A json which contains gist's information. Example:
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
"url": "https:\/\/gist.deblan.org\/en\/view\/55abcfa7771e0\/abcgi72967dd95e3461490dcaa310d728d6adef",
|
|
||||||
"gist": {
|
|
||||||
"Id": 66,
|
|
||||||
"Title": "test prod",
|
|
||||||
"Cipher": false,
|
|
||||||
"Type": "javascript",
|
|
||||||
"File": "55abcfa7771e0",
|
|
||||||
"CreatedAt": "2015-07-19T16:26:15Z",
|
|
||||||
"UpdatedAt": "2015-07-19T16:30:15Z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Code `405`: Method Not Allowed
|
|
||||||
* Code `400`: Bad Request
|
|
||||||
|
|
||||||
Console
|
|
||||||
-------
|
|
||||||
|
|
||||||
### Create and update gists
|
|
||||||
|
|
||||||
```
|
|
||||||
$ app/console --help create
|
|
||||||
$ app/console --help update
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create user
|
|
||||||
|
|
||||||
```
|
|
||||||
$ app/console --help user:create
|
|
||||||
```
|
|
||||||
|
|
||||||
### Show stats
|
|
||||||
|
|
||||||
```
|
|
||||||
$ app/console --help stats
|
|
||||||
```
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
-------------
|
|
||||||
|
|
||||||
### API
|
|
||||||
|
|
||||||
**Personal instance**
|
|
||||||
|
|
||||||
If you install Gist on your server, you have to modify the `base_uri` of the API.
|
|
||||||
Edit `app/bootstrap.php.d/60-api.php` and replace `https://gist.deblan.org/`.
|
|
||||||
|
|
||||||
### Authentication
|
|
||||||
|
|
||||||
**Disabling login**
|
|
||||||
|
|
||||||
Edit `app/bootstrap.php.d/70-security.php` and modify the value of `$app['enable_login']` with `false`.
|
|
||||||
|
|
||||||
**Disabling registration**
|
|
||||||
|
|
||||||
Edit `app/bootstrap.php.d/70-security.php` and modify the value of `$app['enable_registration']` with `false`.
|
|
||||||
|
|
||||||
**Login required to edit a gist**
|
|
||||||
|
|
||||||
Edit `app/bootstrap.php.d/70-security.php` and modify the value of `$app['login_required_to_edit_gist']` with `true`.
|
|
||||||
|
|
||||||
**Login required to view a gist**
|
|
||||||
|
|
||||||
Edit `app/bootstrap.php.d/70-security.php` and modify the value of `$app['login_required_to_view_gist']` with `true`.
|
|
||||||
|
|
||||||
**Login required to view an embeded gist**
|
|
||||||
|
|
||||||
Edit `app/bootstrap.php.d/70-security.php` and modify the value of `$app['login_required_to_view_embeded_gist']` with `true`.
|
|
||||||
|
|
||||||
### Debug
|
|
||||||
|
|
||||||
`app_dev.php` is the development router. Access is granted for an IP range defined in the same file.
|
|
||||||
|
|
||||||
Deployment
|
|
||||||
----------
|
|
||||||
|
|
||||||
Gist uses [Magallanes](http://magephp.com/) to manage deployment.
|
|
||||||
|
|
||||||
**Global installation**
|
|
||||||
|
|
||||||
$ composer global require andres-montanez/magallanes
|
|
||||||
# if the envvar PATH contains "$HOME/bin/"
|
|
||||||
$ ln -s ~/.composer/vendor/bin/mage ~/bin/mage
|
|
||||||
|
|
||||||
**Local installation**
|
|
||||||
|
|
||||||
$ composer require andres-montanez/magallanes
|
|
||||||
|
|
||||||
There is an example of the configuration of an environment in `.mage/config/environment/prod.yml-dist`.
|
|
||||||
|
|
||||||
# global installation
|
|
||||||
$ mage deploy to:prod
|
|
||||||
|
|
||||||
# local installation
|
|
||||||
$ ./vendor/andres-montanez/magallanes/bin/mage deploy to:prod
|
|
||||||
|
|
||||||
Contributors
|
|
||||||
------------
|
|
||||||
|
|
||||||
**Developers**
|
|
||||||
|
|
||||||
* Simon Vieille <contact@deblan.fr>
|
|
||||||
|
|
||||||
**Translators**
|
|
||||||
|
|
||||||
* Simon Vieille <contact@deblan.fr>
|
|
||||||
* Marion Sanchez
|
|
||||||
* Marjorie Da Silva
|
|
||||||
* Mélanie Chanat
|
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Symfony\Component\Config\FileLocator;
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
$app['config.locator.path'] = $app['root_path'].'/app/config/';
|
$app['config.locator.path'] = $app['root_path'].'/app/config/';
|
||||||
|
|
||||||
$app['config.locator'] = function ($app) {
|
$app['config.locator'] = function ($app) {
|
||||||
return new FileLocator($app['config.locator.path']);
|
return new FileLocator($app['config.locator.path']);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$app['settings'] = $app->share(function ($app) {
|
||||||
|
return Yaml::parse($app['config.locator']->locate('config.yml'));
|
||||||
|
});
|
||||||
|
|
|
@ -12,11 +12,3 @@ $app->extend('twig', function ($twig, $app) {
|
||||||
|
|
||||||
return $twig;
|
return $twig;
|
||||||
});
|
});
|
||||||
|
|
||||||
$app['geshi'] = $app->share(function ($app) {
|
|
||||||
$geshi = new GeSHi();
|
|
||||||
$geshi->enable_classes();
|
|
||||||
$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
|
|
||||||
|
|
||||||
return $geshi;
|
|
||||||
});
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use Symfony\Component\HttpFoundation\Cookie;
|
||||||
$app->register(new TranslationServiceProvider(), array(
|
$app->register(new TranslationServiceProvider(), array(
|
||||||
'locale' => 'en',
|
'locale' => 'en',
|
||||||
'locale_fallback' => 'en',
|
'locale_fallback' => 'en',
|
||||||
'locales' => array('en', 'fr', 'es', 'de'),
|
'locales' => array('en', 'fr', 'es', 'de', 'cn', 'pl'),
|
||||||
));
|
));
|
||||||
|
|
||||||
$app['translator'] = $app->extend('translator', function ($translator, $app) {
|
$app['translator'] = $app->extend('translator', function ($translator, $app) {
|
||||||
|
@ -50,7 +50,7 @@ $app->get('/', function (Request $request) use ($app) {
|
||||||
$foundLocale = $app['translator']->getLocale();
|
$foundLocale = $app['translator']->getLocale();
|
||||||
|
|
||||||
foreach ($app['locales'] as $locale) {
|
foreach ($app['locales'] as $locale) {
|
||||||
if ($cookie === $locale || $accept->has($locale)) {
|
if ($cookieValue === $locale || $accept->has($locale)) {
|
||||||
$foundLocale = $locale;
|
$foundLocale = $locale;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,16 @@
|
||||||
use GitWrapper\GitWrapper;
|
use GitWrapper\GitWrapper;
|
||||||
use Gist\Service\Gist;
|
use Gist\Service\Gist;
|
||||||
|
|
||||||
$app['gist_path'] = $app['root_path'].'/data/git';
|
$dataPath = $app['settings']['data']['path'];
|
||||||
|
|
||||||
|
if ($dataPath[0] !== '/') {
|
||||||
|
$app['gist_path'] = $app['root_path'].'/'.$dataPath;
|
||||||
|
} else {
|
||||||
|
$app['gist_path'] = $dataPath;
|
||||||
|
}
|
||||||
|
|
||||||
$app['git_wrapper'] = $app->share(function ($app) {
|
$app['git_wrapper'] = $app->share(function ($app) {
|
||||||
return new GitWrapper('/usr/bin/git');
|
return new GitWrapper($app['settings']['git']['path']);
|
||||||
});
|
});
|
||||||
|
|
||||||
$app['git_working_copy'] = $app->share(function ($app) {
|
$app['git_working_copy'] = $app->share(function ($app) {
|
||||||
|
@ -14,5 +20,5 @@ $app['git_working_copy'] = $app->share(function ($app) {
|
||||||
});
|
});
|
||||||
|
|
||||||
$app['gist'] = $app->share(function ($app) {
|
$app['gist'] = $app->share(function ($app) {
|
||||||
return new Gist($app['gist_path'], $app['git_wrapper'], $app['git_working_copy'], $app['geshi']);
|
return new Gist($app['gist_path'], $app['git_wrapper'], $app['git_working_copy']);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,5 +3,11 @@
|
||||||
use Gist\Api\Client;
|
use Gist\Api\Client;
|
||||||
|
|
||||||
$app['api_client'] = $app->share(function ($app) {
|
$app['api_client'] = $app->share(function ($app) {
|
||||||
return new Client(['base_uri' => 'https://gist.deblan.org/']);
|
$client = new Client(['base_uri' => rtrim($app['settings']['api']['base_url'], '/')]);
|
||||||
|
|
||||||
|
if (!empty($app['settings']['api']['client']['api_key'])) {
|
||||||
|
$client->setApiKey($app['settings']['api']['client']['api_key']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $client;
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,13 +9,9 @@ use Gist\Security\AuthenticationListener;
|
||||||
use Gist\Security\LogoutSuccessHandler;
|
use Gist\Security\LogoutSuccessHandler;
|
||||||
use Silex\Provider\SessionServiceProvider;
|
use Silex\Provider\SessionServiceProvider;
|
||||||
|
|
||||||
$app['enable_registration'] = true;
|
$securitySettings = $app['settings']['security'];
|
||||||
$app['enable_login'] = true;
|
|
||||||
$app['login_required_to_edit_gist'] = false;
|
|
||||||
$app['login_required_to_view_gist'] = false;
|
|
||||||
$app['login_required_to_view_embeded_gist'] = false;
|
|
||||||
|
|
||||||
$app['token'] = 'ThisTokenIsNotSoSecretChangeIt';
|
$app['token'] = $securitySettings['token'];
|
||||||
|
|
||||||
$app['salt_generator'] = $app->share(function ($app) {
|
$app['salt_generator'] = $app->share(function ($app) {
|
||||||
return new SaltGenerator();
|
return new SaltGenerator();
|
||||||
|
@ -77,10 +73,10 @@ $firewall = [
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($app['login_required_to_edit_gist'] || $app['login_required_to_view_gist'] || $app['login_required_to_view_embeded_gist']) {
|
if ($securitySettings['login_required_to_edit_gist'] || $securitySettings['login_required_to_view_gist'] || $securitySettings['login_required_to_view_embeded_gist']) {
|
||||||
$exceptedUriPattern = ['login', 'register'];
|
$exceptedUriPattern = ['login', 'register'];
|
||||||
|
|
||||||
if ($app['login_required_to_view_gist'] === true) {
|
if ($securitySettings['login_required_to_view_gist'] === true) {
|
||||||
$firewall['security.access_rules'][] = ['^/[a-z]{2}/view.*$', 'ROLE_USER'];
|
$firewall['security.access_rules'][] = ['^/[a-z]{2}/view.*$', 'ROLE_USER'];
|
||||||
$firewall['security.access_rules'][] = ['^/[a-z]{2}/revs.*$', 'ROLE_USER'];
|
$firewall['security.access_rules'][] = ['^/[a-z]{2}/revs.*$', 'ROLE_USER'];
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,13 +84,13 @@ if ($app['login_required_to_edit_gist'] || $app['login_required_to_view_gist'] |
|
||||||
$exceptedUriPattern[] = 'revs';
|
$exceptedUriPattern[] = 'revs';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($app['login_required_to_view_embeded_gist'] === true) {
|
if ($securitySettings['login_required_to_view_embeded_gist'] === true) {
|
||||||
$firewall['security.access_rules'][] = ['^/[a-z]{2}/embed.*$', 'ROLE_USER'];
|
$firewall['security.access_rules'][] = ['^/[a-z]{2}/embed.*$', 'ROLE_USER'];
|
||||||
} else {
|
} else {
|
||||||
$exceptedUriPattern[] = 'embed';
|
$exceptedUriPattern[] = 'embed';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($app['login_required_to_edit_gist'] === true) {
|
if ($securitySettings['login_required_to_edit_gist'] === true) {
|
||||||
$firewall['security.access_rules'][] = ['^/[a-z]{2}/(?!('.implode('|', $exceptedUriPattern).')).*$', 'ROLE_USER'];
|
$firewall['security.access_rules'][] = ['^/[a-z]{2}/(?!('.implode('|', $exceptedUriPattern).')).*$', 'ROLE_USER'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
app/bootstrap.php.d/80-cache.php
Normal file
8
app/bootstrap.php.d/80-cache.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Silex\Provider\HttpCacheServiceProvider;
|
||||||
|
|
||||||
|
$app->register(new HttpCacheServiceProvider(), array(
|
||||||
|
'http_cache.cache_dir' => $app['root_path'].'/cache/',
|
||||||
|
'http_cache.esi' => null,
|
||||||
|
));
|
19
app/config/config.yml.dist
Normal file
19
app/config/config.yml.dist
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
security:
|
||||||
|
token: ThisTokenIsNotSoSecretChangeIt
|
||||||
|
enable_registration: true
|
||||||
|
enable_login: true
|
||||||
|
login_required_to_edit_gist: false
|
||||||
|
login_required_to_view_gist: false
|
||||||
|
login_required_to_view_embeded_gist: false
|
||||||
|
api:
|
||||||
|
enabled: true
|
||||||
|
api_key_required: false
|
||||||
|
base_url: 'https://gist.deblan.org/'
|
||||||
|
client:
|
||||||
|
api_key:
|
||||||
|
data:
|
||||||
|
path: data/git
|
||||||
|
git:
|
||||||
|
path: /usr/bin/git
|
||||||
|
theme:
|
||||||
|
name: dark
|
|
@ -4,9 +4,9 @@ propel:
|
||||||
default:
|
default:
|
||||||
adapter: mysql
|
adapter: mysql
|
||||||
classname: Propel\Runtime\Connection\ConnectionWrapper
|
classname: Propel\Runtime\Connection\ConnectionWrapper
|
||||||
dsn: "mysql:host=localhost;dbname=gist"
|
dsn: "mysql:host=DATABASE_HOST;dbname=DATABASE_NAME"
|
||||||
user: root
|
user: "DATABASE_USERNAME"
|
||||||
password: root
|
password: "DATABASE_PASSWORD"
|
||||||
settings:
|
settings:
|
||||||
charset: utf8
|
charset: utf8
|
||||||
queries:
|
queries:
|
31
app/config/propel.yaml.dist-sqlite
Normal file
31
app/config/propel.yaml.dist-sqlite
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
propel:
|
||||||
|
database:
|
||||||
|
connections:
|
||||||
|
default:
|
||||||
|
adapter: sqlite
|
||||||
|
classname: Propel\Runtime\Connection\ConnectionWrapper
|
||||||
|
dsn: "sqlite:DATABASE_PATH"
|
||||||
|
user: ~
|
||||||
|
password: ~
|
||||||
|
settings:
|
||||||
|
charset: utf8
|
||||||
|
queries:
|
||||||
|
|
||||||
|
paths:
|
||||||
|
projectDir: src/
|
||||||
|
schemaDir: src/
|
||||||
|
outputDir: src/
|
||||||
|
phpDir: src/
|
||||||
|
phpConfDir: app/config/propel
|
||||||
|
sqlDir: app/propel/sql
|
||||||
|
migrationDir: app/propel/migration
|
||||||
|
|
||||||
|
runtime:
|
||||||
|
defaultConnection: default
|
||||||
|
connections: [default]
|
||||||
|
|
||||||
|
generator:
|
||||||
|
defaultConnection: default
|
||||||
|
connections: [default]
|
||||||
|
objectModel:
|
||||||
|
addClassLevelComment: false
|
|
@ -57,10 +57,18 @@ revisions:
|
||||||
path: /revs/{gist}
|
path: /revs/{gist}
|
||||||
defaults: {_controller: Gist\Controller\ViewController::revisionsAction, _locale: en}
|
defaults: {_controller: Gist\Controller\ViewController::revisionsAction, _locale: en}
|
||||||
|
|
||||||
|
api_list:
|
||||||
|
path: /api/list/{apiKey}
|
||||||
|
defaults: {_controller: Gist\Controller\ApiController::listAction, _locale: en, apiKey: null}
|
||||||
|
|
||||||
api_create:
|
api_create:
|
||||||
path: /api/create
|
path: /api/create/{apiKey}
|
||||||
defaults: {_controller: Gist\Controller\ApiController::createAction, _locale: en}
|
defaults: {_controller: Gist\Controller\ApiController::createAction, _locale: en, apiKey: null}
|
||||||
|
|
||||||
api_update:
|
api_update:
|
||||||
path: /api/update/{gist}
|
path: /api/update/{gist}/{apiKey}
|
||||||
defaults: {_controller: Gist\Controller\ApiController::updateAction, _locale: en}
|
defaults: {_controller: Gist\Controller\ApiController::updateAction, _locale: en, apiKey: null}
|
||||||
|
|
||||||
|
api_delete:
|
||||||
|
path: /api/delete/{gist}/{apiKey}
|
||||||
|
defaults: {_controller: Gist\Controller\ApiController::deleteAction, _locale: en, apiKey: null}
|
||||||
|
|
|
@ -2,15 +2,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Gist\Command\CreateCommand;
|
use Gist\Command\CreateCommand;
|
||||||
|
use Gist\Command\ListCommand;
|
||||||
use Gist\Command\UpdateCommand;
|
use Gist\Command\UpdateCommand;
|
||||||
use Gist\Command\StatsCommand;
|
use Gist\Command\StatsCommand;
|
||||||
|
use Gist\Command\DeleteCommand;
|
||||||
use Gist\Command\UserCreateCommand;
|
use Gist\Command\UserCreateCommand;
|
||||||
|
use Gist\Command\Migration\UpgradeTo1p4p1Command;
|
||||||
|
|
||||||
$app = require __DIR__.'/bootstrap.php';
|
$app = require __DIR__.'/bootstrap.php';
|
||||||
|
|
||||||
$app['console']->add(new CreateCommand());
|
$app['console']->add(new CreateCommand());
|
||||||
|
$app['console']->add(new ListCommand());
|
||||||
$app['console']->add(new UpdateCommand());
|
$app['console']->add(new UpdateCommand());
|
||||||
|
$app['console']->add(new DeleteCommand());
|
||||||
$app['console']->add(new StatsCommand());
|
$app['console']->add(new StatsCommand());
|
||||||
$app['console']->add(new UserCreateCommand());
|
$app['console']->add(new UserCreateCommand());
|
||||||
|
$app['console']->add(new UpgradeTo1p4p1Command());
|
||||||
|
|
||||||
$app['console']->run();
|
$app['console']->run();
|
||||||
|
|
108
app/locales/cn.yml
Normal file
108
app/locales/cn.yml
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
app:
|
||||||
|
title: '#!GIST'
|
||||||
|
title_prefix: '#!GIST - '
|
||||||
|
|
||||||
|
menu:
|
||||||
|
home:
|
||||||
|
title: '首页'
|
||||||
|
about:
|
||||||
|
title: '关于'
|
||||||
|
my:
|
||||||
|
login:
|
||||||
|
title: '登陆'
|
||||||
|
logout:
|
||||||
|
title: '注销'
|
||||||
|
register:
|
||||||
|
title: '注册'
|
||||||
|
my:
|
||||||
|
title: '账号'
|
||||||
|
|
||||||
|
my:
|
||||||
|
title: '我的 Gist'
|
||||||
|
nothing: '这家伙很懒,暂时没有内容'
|
||||||
|
api:
|
||||||
|
title: 'API'
|
||||||
|
warning: 'Keep it <strong>secret!</strong>'
|
||||||
|
form:
|
||||||
|
generate: 'Regenerate'
|
||||||
|
|
||||||
|
gist:
|
||||||
|
untitled: '未命名'
|
||||||
|
404:
|
||||||
|
title: '哇!'
|
||||||
|
message: '这个 gist 未找到...'
|
||||||
|
action:
|
||||||
|
view: '查看'
|
||||||
|
history: '历史版本'
|
||||||
|
raw: '源文件'
|
||||||
|
download: '下载'
|
||||||
|
clone: '克隆'
|
||||||
|
embed: '引用'
|
||||||
|
add: '新建'
|
||||||
|
|
||||||
|
date:
|
||||||
|
format: 'Y-m-d h:i:s'
|
||||||
|
|
||||||
|
footer:
|
||||||
|
text: '<p>Powered by <a href="https://gitnet.fr/deblan/gist">GIST</a>, it''s open source :) - <a href="https://gitnet.fr/deblan/gist/wiki/1.4-API/">API</a></p>'
|
||||||
|
|
||||||
|
login:
|
||||||
|
login:
|
||||||
|
title: '登陆'
|
||||||
|
invalid: '用户名或密码错误'
|
||||||
|
form:
|
||||||
|
username:
|
||||||
|
placeholder: '用户名'
|
||||||
|
password:
|
||||||
|
placeholder: '密码'
|
||||||
|
remember_me:
|
||||||
|
label: '记住我'
|
||||||
|
register:
|
||||||
|
title: '注册新账号'
|
||||||
|
already_exists: '改用户名已被使用'
|
||||||
|
registred: '恭喜您,您的账号已经注册成功!'
|
||||||
|
form:
|
||||||
|
username:
|
||||||
|
placeholder: '用户名'
|
||||||
|
current_password:
|
||||||
|
placeholder: '当前密码'
|
||||||
|
password:
|
||||||
|
placeholder: '新密码'
|
||||||
|
|
||||||
|
form:
|
||||||
|
error:
|
||||||
|
password: '密码错误'
|
||||||
|
not_blank: '该选项不可为空'
|
||||||
|
title:
|
||||||
|
placeholder: '标题'
|
||||||
|
cipher:
|
||||||
|
label: '加密: %value%'
|
||||||
|
choice:
|
||||||
|
anyway: '随意'
|
||||||
|
yes: '是'
|
||||||
|
no: '否'
|
||||||
|
submit: '提交'
|
||||||
|
filter: '过滤器'
|
||||||
|
confirm: '确认此次操作?'
|
||||||
|
success:
|
||||||
|
password: '密码已更新'
|
||||||
|
gist: 'Gist 已移除'
|
||||||
|
type:
|
||||||
|
label: '语言: %value%'
|
||||||
|
choice:
|
||||||
|
all: 'All'
|
||||||
|
html: 'HTML'
|
||||||
|
xml: 'XML'
|
||||||
|
css: 'CSS'
|
||||||
|
javascript: 'JAVASCRIPT'
|
||||||
|
php: 'PHP'
|
||||||
|
sql: 'SQL'
|
||||||
|
yaml: 'YAML'
|
||||||
|
markdown: 'MARKDOWN'
|
||||||
|
perl: 'PERL'
|
||||||
|
c: 'C/C++'
|
||||||
|
asp: 'ASP'
|
||||||
|
python: 'PYTHON'
|
||||||
|
bash: 'BASH'
|
||||||
|
actionscript3: 'ACTION SCRIPT'
|
||||||
|
text: 'TEXT'
|
|
@ -20,6 +20,11 @@ app:
|
||||||
my:
|
my:
|
||||||
title: 'Meine Gists'
|
title: 'Meine Gists'
|
||||||
nothing: 'Nichts zu finden (momentan)!'
|
nothing: 'Nichts zu finden (momentan)!'
|
||||||
|
api:
|
||||||
|
title: 'API'
|
||||||
|
warning: 'Keep it <strong>secret!</strong>'
|
||||||
|
form:
|
||||||
|
generate: 'Regenerate'
|
||||||
|
|
||||||
gist:
|
gist:
|
||||||
untitled: 'Ohne Titel'
|
untitled: 'Ohne Titel'
|
||||||
|
@ -32,14 +37,14 @@ gist:
|
||||||
raw: 'RAW'
|
raw: 'RAW'
|
||||||
download: 'Herunterladen'
|
download: 'Herunterladen'
|
||||||
clone: 'Klonen'
|
clone: 'Klonen'
|
||||||
embed: 'Einfügen:'
|
embed: 'Einfügen'
|
||||||
add: 'Hinzufügen'
|
add: 'Hinzufügen'
|
||||||
|
|
||||||
date:
|
date:
|
||||||
format: 'Y-m-d h:i:s'
|
format: 'Y-m-d h:i:s'
|
||||||
|
|
||||||
footer:
|
footer:
|
||||||
text: '<p>Powered by <a href="https://gitnet.fr/deblan/gist">GIST</a>, it''s open source :) - <a href="https://gitnet.fr/deblan/gist#api">API</a></p>'
|
text: '<p>Powered by <a href="https://gitnet.fr/deblan/gist">GIST</a>, it''s open source :) - <a href="https://gitnet.fr/deblan/gist/wiki/1.4-API/">API</a></p>'
|
||||||
|
|
||||||
login:
|
login:
|
||||||
login:
|
login:
|
||||||
|
@ -93,6 +98,7 @@ form:
|
||||||
php: 'PHP'
|
php: 'PHP'
|
||||||
sql: 'SQL'
|
sql: 'SQL'
|
||||||
yaml: 'YAML'
|
yaml: 'YAML'
|
||||||
|
markdown: 'MARKDOWN'
|
||||||
perl: 'PERL'
|
perl: 'PERL'
|
||||||
c: 'C/C++'
|
c: 'C/C++'
|
||||||
asp: 'ASP'
|
asp: 'ASP'
|
||||||
|
|
|
@ -20,6 +20,12 @@ app:
|
||||||
my:
|
my:
|
||||||
title: 'My gists'
|
title: 'My gists'
|
||||||
nothing: 'Nothing yet!'
|
nothing: 'Nothing yet!'
|
||||||
|
api:
|
||||||
|
title: 'API'
|
||||||
|
warning: 'Keep it <strong>secret!</strong>'
|
||||||
|
form:
|
||||||
|
generate: 'Regenerate'
|
||||||
|
|
||||||
|
|
||||||
gist:
|
gist:
|
||||||
untitled: 'Untitled'
|
untitled: 'Untitled'
|
||||||
|
@ -32,14 +38,14 @@ gist:
|
||||||
raw: 'RAW'
|
raw: 'RAW'
|
||||||
download: 'Download'
|
download: 'Download'
|
||||||
clone: 'Clone'
|
clone: 'Clone'
|
||||||
embed: 'Embed:'
|
embed: 'Embed'
|
||||||
add: 'New'
|
add: 'New'
|
||||||
|
|
||||||
date:
|
date:
|
||||||
format: 'Y-m-d h:i:s'
|
format: 'Y-m-d h:i:s'
|
||||||
|
|
||||||
footer:
|
footer:
|
||||||
text: '<p>Powered by <a href="https://gitnet.fr/deblan/gist">GIST</a>, it''s open source :) - <a href="https://gitnet.fr/deblan/gist#api">API</a></p>'
|
text: '<p>Powered by <a href="https://gitnet.fr/deblan/gist">GIST</a>, it''s open source :) - <a href="https://gitnet.fr/deblan/gist/wiki/1.4-API/">API</a></p>'
|
||||||
|
|
||||||
login:
|
login:
|
||||||
login:
|
login:
|
||||||
|
@ -93,6 +99,7 @@ form:
|
||||||
php: 'PHP'
|
php: 'PHP'
|
||||||
sql: 'SQL'
|
sql: 'SQL'
|
||||||
yaml: 'YAML'
|
yaml: 'YAML'
|
||||||
|
markdown: 'MARKDOWN'
|
||||||
perl: 'PERL'
|
perl: 'PERL'
|
||||||
c: 'C/C++'
|
c: 'C/C++'
|
||||||
asp: 'ASP'
|
asp: 'ASP'
|
||||||
|
|
|
@ -20,6 +20,11 @@ app:
|
||||||
my:
|
my:
|
||||||
title: 'Mis Gists'
|
title: 'Mis Gists'
|
||||||
nothing: 'Nada por ahora.'
|
nothing: 'Nada por ahora.'
|
||||||
|
api:
|
||||||
|
title: 'API'
|
||||||
|
warning: 'Keep it <strong>secret!</strong>'
|
||||||
|
form:
|
||||||
|
generate: 'Regenerate'
|
||||||
|
|
||||||
gist:
|
gist:
|
||||||
untitled: 'Sin título'
|
untitled: 'Sin título'
|
||||||
|
@ -32,14 +37,14 @@ gist:
|
||||||
raw: 'RAW'
|
raw: 'RAW'
|
||||||
download: 'Descargar'
|
download: 'Descargar'
|
||||||
clone: 'Clonar'
|
clone: 'Clonar'
|
||||||
embed: 'Insertar : '
|
embed: 'Insertar'
|
||||||
add: 'Añadir'
|
add: 'Añadir'
|
||||||
|
|
||||||
date:
|
date:
|
||||||
format: 'd/m/Y H\hi s\s'
|
format: 'd/m/Y H\hi s\s'
|
||||||
|
|
||||||
footer:
|
footer:
|
||||||
text: '<p>Impulsado por <a href="https://gitnet.fr/deblan/gist">GIST</a>, es libre :) - <a href="https://gitnet.fr/deblan/gist#api">API</a></p>'
|
text: '<p>Impulsado por <a href="https://gitnet.fr/deblan/gist">GIST</a>, es libre :) - <a href="https://gitnet.fr/deblan/gist/wiki/1.4-API/">API</a></p>'
|
||||||
|
|
||||||
login:
|
login:
|
||||||
login:
|
login:
|
||||||
|
@ -93,6 +98,7 @@ form:
|
||||||
php: 'PHP'
|
php: 'PHP'
|
||||||
sql: 'SQL'
|
sql: 'SQL'
|
||||||
yaml: 'YAML'
|
yaml: 'YAML'
|
||||||
|
markdown: 'MARKDOWN'
|
||||||
perl: 'PERL'
|
perl: 'PERL'
|
||||||
c: 'C/C++'
|
c: 'C/C++'
|
||||||
asp: 'ASP'
|
asp: 'ASP'
|
||||||
|
|
|
@ -20,6 +20,11 @@ app:
|
||||||
my:
|
my:
|
||||||
title: 'Mes Gists'
|
title: 'Mes Gists'
|
||||||
nothing: 'Rien pour le moment !'
|
nothing: 'Rien pour le moment !'
|
||||||
|
api:
|
||||||
|
title: 'API'
|
||||||
|
warning: 'Gardez-la <strong>secrète !</strong>'
|
||||||
|
form:
|
||||||
|
generate: 'Regénérer'
|
||||||
|
|
||||||
gist:
|
gist:
|
||||||
untitled: 'Sans titre'
|
untitled: 'Sans titre'
|
||||||
|
@ -32,14 +37,14 @@ gist:
|
||||||
raw: 'RAW'
|
raw: 'RAW'
|
||||||
download: 'Télécharger'
|
download: 'Télécharger'
|
||||||
clone: 'Clôner'
|
clone: 'Clôner'
|
||||||
embed: 'Insérer : '
|
embed: 'Insérer'
|
||||||
add: 'Ajouter'
|
add: 'Ajouter'
|
||||||
|
|
||||||
date:
|
date:
|
||||||
format: 'd/m/Y H\hi s\s'
|
format: 'd/m/Y H\hi s\s'
|
||||||
|
|
||||||
footer:
|
footer:
|
||||||
text: '<p>Propulsé par <a href="https://gitnet.fr/deblan/gist">GIST</a>, c''est libre :) - <a href="https://gitnet.fr/deblan/gist#api">API</a></p>'
|
text: '<p>Propulsé par <a href="https://gitnet.fr/deblan/gist">GIST</a>, c''est libre :) - <a href="https://gitnet.fr/deblan/gist/wiki/1.4-API/">API</a></p>'
|
||||||
|
|
||||||
login:
|
login:
|
||||||
login:
|
login:
|
||||||
|
@ -93,6 +98,7 @@ form:
|
||||||
php: 'PHP'
|
php: 'PHP'
|
||||||
sql: 'SQL'
|
sql: 'SQL'
|
||||||
yaml: 'YAML'
|
yaml: 'YAML'
|
||||||
|
markdown: 'MARKDOWN'
|
||||||
perl: 'PERL'
|
perl: 'PERL'
|
||||||
c: 'C/C++'
|
c: 'C/C++'
|
||||||
asp: 'ASP'
|
asp: 'ASP'
|
||||||
|
|
109
app/locales/pl.yml
Normal file
109
app/locales/pl.yml
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
app:
|
||||||
|
title: '#!GIST'
|
||||||
|
title_prefix: '#!GIST - '
|
||||||
|
|
||||||
|
menu:
|
||||||
|
home:
|
||||||
|
title: 'Home'
|
||||||
|
about:
|
||||||
|
title: 'O projekcie'
|
||||||
|
my:
|
||||||
|
login:
|
||||||
|
title: 'Logowanie'
|
||||||
|
logout:
|
||||||
|
title: 'Wylogowanie'
|
||||||
|
register:
|
||||||
|
title: 'Rejestracja'
|
||||||
|
my:
|
||||||
|
title: 'Konta'
|
||||||
|
|
||||||
|
my:
|
||||||
|
title: 'Moje wklejki'
|
||||||
|
nothing: 'Nie ma jeszcze nic!'
|
||||||
|
api:
|
||||||
|
title: 'API'
|
||||||
|
warning: 'Trzymaj to w <strong>sekrecie!</strong>'
|
||||||
|
form:
|
||||||
|
generate: 'Wygeneruj nowy'
|
||||||
|
|
||||||
|
|
||||||
|
gist:
|
||||||
|
untitled: 'Bez tytułu'
|
||||||
|
404:
|
||||||
|
title: 'Oops!'
|
||||||
|
message: 'Wklejka nie została znaleziona...'
|
||||||
|
action:
|
||||||
|
view: 'Podgląd'
|
||||||
|
history: 'Commit(s)'
|
||||||
|
raw: 'RAW'
|
||||||
|
download: 'Pobierz'
|
||||||
|
clone: 'Sklonuj'
|
||||||
|
embed: 'Embed'
|
||||||
|
add: 'Nowa'
|
||||||
|
|
||||||
|
date:
|
||||||
|
format: 'Y-m-d h:i:s'
|
||||||
|
|
||||||
|
footer:
|
||||||
|
text: '<p>Napędzane przez <a href="https://gitnet.fr/deblan/gist">GIST</a>, to jest open source :) - <a href="https://gitnet.fr/deblan/gist/wiki/1.4-API/">API</a></p>'
|
||||||
|
|
||||||
|
login:
|
||||||
|
login:
|
||||||
|
title: 'Logowanie'
|
||||||
|
invalid: 'Nie prawidłowy login lub hasło.'
|
||||||
|
form:
|
||||||
|
username:
|
||||||
|
placeholder: 'Login'
|
||||||
|
password:
|
||||||
|
placeholder: 'Hasło'
|
||||||
|
remember_me:
|
||||||
|
label: 'Pamiętaj'
|
||||||
|
register:
|
||||||
|
title: 'Nowe konto'
|
||||||
|
already_exists: 'Ta nazwa użytkownika jest już zarejestrowana!'
|
||||||
|
registred: 'Gratulacje, twoje konto zostało utworzone!'
|
||||||
|
form:
|
||||||
|
username:
|
||||||
|
placeholder: 'Login'
|
||||||
|
current_password:
|
||||||
|
placeholder: 'Obecne hasło'
|
||||||
|
password:
|
||||||
|
placeholder: 'Hasło'
|
||||||
|
|
||||||
|
form:
|
||||||
|
error:
|
||||||
|
password: 'Nie prawidłowe hasło.'
|
||||||
|
not_blank: 'To pole nie powinno być puste!'
|
||||||
|
title:
|
||||||
|
placeholder: 'Tytuł'
|
||||||
|
cipher:
|
||||||
|
label: 'Szyfrowanie: %value%'
|
||||||
|
choice:
|
||||||
|
anyway: 'Tak czy inaczej'
|
||||||
|
yes: 'Tak'
|
||||||
|
no: 'Nie'
|
||||||
|
submit: 'Wyślij'
|
||||||
|
filter: 'Filtr'
|
||||||
|
confirm: 'Potwierdzasz?'
|
||||||
|
success:
|
||||||
|
password: 'Hasło zostało zaktualizowane.'
|
||||||
|
gist: 'Wklejka została usunięta.'
|
||||||
|
type:
|
||||||
|
label: 'Język: %value%'
|
||||||
|
choice:
|
||||||
|
all: 'All'
|
||||||
|
html: 'HTML'
|
||||||
|
xml: 'XML'
|
||||||
|
css: 'CSS'
|
||||||
|
javascript: 'JAVASCRIPT'
|
||||||
|
php: 'PHP'
|
||||||
|
sql: 'SQL'
|
||||||
|
yaml: 'YAML'
|
||||||
|
markdown: 'MARKDOWN'
|
||||||
|
perl: 'PERL'
|
||||||
|
c: 'C/C++'
|
||||||
|
asp: 'ASP'
|
||||||
|
python: 'PYTHON'
|
||||||
|
bash: 'BASH'
|
||||||
|
actionscript3: 'ACTION SCRIPT'
|
||||||
|
text: 'TEXT'
|
22
bower.json
22
bower.json
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"name": "gist",
|
|
||||||
"version": "0.0.3",
|
|
||||||
"authors": [
|
|
||||||
"Simon Vieille <simon@deblan.fr>"
|
|
||||||
],
|
|
||||||
"description": "GIST is an open-source application to share code.",
|
|
||||||
"main": "web/index.php",
|
|
||||||
"keywords": [
|
|
||||||
"Gist",
|
|
||||||
"GIT"
|
|
||||||
],
|
|
||||||
"license": "LGPL",
|
|
||||||
"homepage": "https://gitnet.fr/deblan/gist",
|
|
||||||
"dependencies": {
|
|
||||||
"bootstrap": "3.3.4",
|
|
||||||
"flag-icon-css": "0.7.1",
|
|
||||||
"SyntaxHighlighter": "3.0.83",
|
|
||||||
"iframe-resizer": "2.8.6",
|
|
||||||
"jsdiff": "~2.2.2"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"name": "deblan/gist",
|
||||||
|
"license": "GPL-3.0-only",
|
||||||
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
"geshi/geshi": "dev-master",
|
|
||||||
"silex/silex": "1.3.x-dev",
|
"silex/silex": "1.3.x-dev",
|
||||||
"symfony/yaml": "~2.6",
|
"symfony/yaml": "~2.6",
|
||||||
"symfony/twig-bridge": "~2.6",
|
"symfony/twig-bridge": "~2.6",
|
||||||
|
@ -13,6 +15,17 @@
|
||||||
"guzzlehttp/guzzle": "~6.0",
|
"guzzlehttp/guzzle": "~6.0",
|
||||||
"symfony/security": "^2.7"
|
"symfony/security": "^2.7"
|
||||||
},
|
},
|
||||||
|
"scripts": {
|
||||||
|
"gist-scripts": [
|
||||||
|
"Gist\\Composer\\PostInstallHandler::execute"
|
||||||
|
],
|
||||||
|
"post-install-cmd": [
|
||||||
|
"@gist-scripts"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@gist-scripts"
|
||||||
|
]
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": {
|
"psr-0": {
|
||||||
"": "src/"
|
"": "src/"
|
||||||
|
|
9
package.json
Normal file
9
package.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^3.4.1",
|
||||||
|
"diff": "^3.5.0",
|
||||||
|
"flag-icon-css": "^0.8.6",
|
||||||
|
"iframe-resizer": "^2.8.10",
|
||||||
|
"jquery": ">=3.4.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,31 +12,53 @@ use GuzzleHttp\Client as BaseClient;
|
||||||
class Client extends BaseClient
|
class Client extends BaseClient
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* URI of creation
|
* URI of creation.
|
||||||
*
|
*
|
||||||
* @const string
|
* @const string
|
||||||
*/
|
*/
|
||||||
const CREATE = '/en/api/create';
|
const CREATE = '/en/api/create';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URI of updating
|
* URI of update.
|
||||||
*
|
*
|
||||||
* @const string
|
* @const string
|
||||||
*/
|
*/
|
||||||
const UPDATE = '/en/api/update/{gist}';
|
const UPDATE = '/en/api/update/{gist}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a gist
|
* URI of delete.
|
||||||
|
*
|
||||||
|
* @const string
|
||||||
|
*/
|
||||||
|
const DELETE = '/en/api/delete/{gist}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI of list.
|
||||||
|
*
|
||||||
|
* @const string
|
||||||
|
*/
|
||||||
|
const LIST = '/en/api/list';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The API key.
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a gist.
|
||||||
*
|
*
|
||||||
* @param string $title The title
|
* @param string $title The title
|
||||||
* @param string $type The type
|
* @param string $type The type
|
||||||
* @param string $content The content
|
* @param string $content The content
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function create($title, $type, $content)
|
public function create($title, $type, $content)
|
||||||
{
|
{
|
||||||
$response = $this->post(
|
$response = $this->post(
|
||||||
self::CREATE,
|
$this->mergeApiKey(self::CREATE),
|
||||||
array(
|
array(
|
||||||
'form_params' => array(
|
'form_params' => array(
|
||||||
'form' => array(
|
'form' => array(
|
||||||
|
@ -56,7 +78,7 @@ class Client extends BaseClient
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones and update a gist
|
* Clones and update a gist.
|
||||||
*
|
*
|
||||||
* @param string $gist Gist's ID
|
* @param string $gist Gist's ID
|
||||||
* @param string $content The content
|
* @param string $content The content
|
||||||
|
@ -66,7 +88,7 @@ class Client extends BaseClient
|
||||||
public function update($gist, $content)
|
public function update($gist, $content)
|
||||||
{
|
{
|
||||||
$response = $this->post(
|
$response = $this->post(
|
||||||
str_replace('{gist}', $gist, self::UPDATE),
|
str_replace('{gist}', $gist, $this->mergeApiKey(self::UPDATE)),
|
||||||
array(
|
array(
|
||||||
'form_params' => array(
|
'form_params' => array(
|
||||||
'form' => array(
|
'form' => array(
|
||||||
|
@ -82,4 +104,81 @@ class Client extends BaseClient
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a gist.
|
||||||
|
*
|
||||||
|
* @param string $gist Gist's ID
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function delete($gist)
|
||||||
|
{
|
||||||
|
$response = $this->post(str_replace('{gist}', $gist, $this->mergeApiKey(self::DELETE)));
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
return json_decode($response->getBody()->getContents(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists the user's gists.
|
||||||
|
*
|
||||||
|
* @param string $gist Gist's ID
|
||||||
|
* @param string $content The content
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function list()
|
||||||
|
{
|
||||||
|
$response = $this->get($this->mergeApiKey(self::LIST));
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
return json_decode($response->getBody()->getContents(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merges the API key with the given url.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function mergeApiKey($url)
|
||||||
|
{
|
||||||
|
if (empty($this->apiKey)) {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtrim($url, '/').'/'.$this->apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the value of "apiKey".
|
||||||
|
*
|
||||||
|
* @param string|null $apiKey
|
||||||
|
*
|
||||||
|
* @return Client
|
||||||
|
*/
|
||||||
|
public function setApiKey($apiKey)
|
||||||
|
{
|
||||||
|
$this->apiKey = $apiKey;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the value of "apiKey".
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApiKey()
|
||||||
|
{
|
||||||
|
return $this->apiKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Propel\Runtime\Parser\YamlParser;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class CreateCommand.
|
* class CreateCommand.
|
||||||
|
@ -27,8 +29,9 @@ class CreateCommand extends Command
|
||||||
->addArgument('input', InputArgument::REQUIRED, 'Input')
|
->addArgument('input', InputArgument::REQUIRED, 'Input')
|
||||||
->addArgument('type', InputArgument::OPTIONAL, 'Type', 'text')
|
->addArgument('type', InputArgument::OPTIONAL, 'Type', 'text')
|
||||||
->addOption('title', 't', InputOption::VALUE_REQUIRED, 'Title of the gist')
|
->addOption('title', 't', InputOption::VALUE_REQUIRED, 'Title of the gist')
|
||||||
->addOption('show-url', 'u', InputOption::VALUE_NONE, 'Display only the gist url')
|
->addOption('all', 'a', InputOption::VALUE_NONE, 'Display all the response')
|
||||||
->addOption('show-id', 'i', InputOption::VALUE_NONE, 'Display only the gist Id')
|
->addOption('id', 'i', InputOption::VALUE_NONE, 'Display only the id of the gist')
|
||||||
|
->addOption('json', 'j', InputOption::VALUE_NONE, 'Format the response to json')
|
||||||
->setHelp(<<<EOF
|
->setHelp(<<<EOF
|
||||||
Provides a client to create a gist using the API.
|
Provides a client to create a gist using the API.
|
||||||
|
|
||||||
|
@ -44,11 +47,14 @@ Options:
|
||||||
<info>--title</info>, <info>-t</info>
|
<info>--title</info>, <info>-t</info>
|
||||||
Defines a title
|
Defines a title
|
||||||
|
|
||||||
<info>--show-id</info>, <info>-i</info>
|
<info>--id</info>, <info>-i</info>
|
||||||
Display only the Id of the gist
|
Display only the id of the gist
|
||||||
|
|
||||||
<info>--show-url</info>, <info>-u</info>
|
<info>--all</info>, <info>-a</info>
|
||||||
Display only the url of the gist
|
Display all the response
|
||||||
|
|
||||||
|
<info>--json</info>, <info>-j</info>
|
||||||
|
Format the response to json
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -58,11 +64,10 @@ EOF
|
||||||
*/
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
//$output->writeln(sprintf('<comment>%s</comment> bar.', 'test'));
|
|
||||||
|
|
||||||
$file = $input->getArgument('input');
|
$file = $input->getArgument('input');
|
||||||
$type = $input->getArgument('type');
|
$type = $input->getArgument('type');
|
||||||
$title = $input->getOption('title');
|
$title = $input->getOption('title');
|
||||||
|
$json = $input->getOption('json');
|
||||||
|
|
||||||
if ($file === '-') {
|
if ($file === '-') {
|
||||||
$content = file_get_contents('php://stdin');
|
$content = file_get_contents('php://stdin');
|
||||||
|
@ -94,19 +99,17 @@ EOF
|
||||||
|
|
||||||
$gist = $this->getSilexApplication()['api_client']->create($title, $type, $content);
|
$gist = $this->getSilexApplication()['api_client']->create($title, $type, $content);
|
||||||
|
|
||||||
if ($input->getOption('show-url')) {
|
if ($input->getOption('id')) {
|
||||||
$output->writeln($gist['url']);
|
$id = isset($gist['gist']['id']) ? $gist['gist']['id'] : $gist['gist']['Id'];
|
||||||
|
$result = $json ? json_encode(array('id' => $id)) : $id;
|
||||||
return true;
|
} elseif ($input->getOption('all')) {
|
||||||
|
$result = $json ? json_encode($gist) : Yaml::dump($gist);
|
||||||
|
} else {
|
||||||
|
$url = $gist['url'];
|
||||||
|
$result = $json ? json_encode(array('url' => $url)) : $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($input->getOption('show-id')) {
|
$output->writeln($result);
|
||||||
$output->writeln($gist['gist']['Id']);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$output->writeln(json_encode($gist));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
48
src/Gist/Command/DeleteCommand.php
Normal file
48
src/Gist/Command/DeleteCommand.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Gist\Command;
|
||||||
|
|
||||||
|
use Knp\Command\Command;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class DeleteCommand.
|
||||||
|
*
|
||||||
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
|
*/
|
||||||
|
class DeleteCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('delete')
|
||||||
|
->setDescription('Delete a gist using the API')
|
||||||
|
->addOption('gist', null, InputOption::VALUE_REQUIRED, 'Id or File of the gist')
|
||||||
|
->setHelp(<<<'EOF'
|
||||||
|
Provides a client to delete a gist using the API.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
none.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
<info>--gist</info>
|
||||||
|
Defines the Gist to delete by using its Id or its File
|
||||||
|
EOF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$result = $this->getSilexApplication()['api_client']->delete($input->getOption('gist'));
|
||||||
|
|
||||||
|
$output->writeln(empty($result['error']) ? 'OK' : '<error>An error occured.</error>');
|
||||||
|
}
|
||||||
|
}
|
59
src/Gist/Command/ListCommand.php
Normal file
59
src/Gist/Command/ListCommand.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Gist\Command;
|
||||||
|
|
||||||
|
use Knp\Command\Command;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Propel\Runtime\Parser\YamlParser;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
use Symfony\Component\Console\Helper\Table;
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class ListCommand.
|
||||||
|
*
|
||||||
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
|
*/
|
||||||
|
class ListCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('gists')
|
||||||
|
->setDescription('List gists using the API');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$gists = $this->getSilexApplication()['api_client']->list();
|
||||||
|
$rows = [];
|
||||||
|
|
||||||
|
foreach ($gists as $gist) {
|
||||||
|
$rows[] = array(
|
||||||
|
$gist['id'],
|
||||||
|
$gist['title'],
|
||||||
|
$gist['cipher'] ? 'y' : 'n',
|
||||||
|
$gist['type'],
|
||||||
|
(new DateTime($gist['createdAt']))->format('Y-m-d H:i:s'),
|
||||||
|
(new DateTime($gist['updatedAt']))->format('Y-m-d H:i:s'),
|
||||||
|
$gist['url'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = new Table($output);
|
||||||
|
$table
|
||||||
|
->setHeaders(array('ID', 'Title', 'Cipher', 'Type', 'Created At', 'Updated At', 'url'))
|
||||||
|
->setRows($rows);
|
||||||
|
|
||||||
|
$table->render();
|
||||||
|
}
|
||||||
|
}
|
44
src/Gist/Command/Migration/UpgradeTo1p4p1Command.php
Normal file
44
src/Gist/Command/Migration/UpgradeTo1p4p1Command.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Gist\Command\Migration;
|
||||||
|
|
||||||
|
use Knp\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Gist\Model\GistQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class UpgradeTo1p4p1Command.
|
||||||
|
*
|
||||||
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
|
*/
|
||||||
|
class UpgradeTo1p4p1Command extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('migrate:to:v1.4.1')
|
||||||
|
->setDescription('Migrates database entries to >= v1.4.1')
|
||||||
|
->setHelp('The <info>%command.name%</info> migrates database entries to >= v1.4.1');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$app = $this->getSilexApplication();
|
||||||
|
$gists = GistQuery::create()
|
||||||
|
->filterByCommits(0)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
foreach ($gists as $gist) {
|
||||||
|
$commits = $app['gist']->getNumberOfCommits($gist);
|
||||||
|
$gist->setCommits($commits);
|
||||||
|
$gist->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,12 +58,7 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
$languages[$gist->getType()]++;
|
$languages[$gist->getType()]++;
|
||||||
try {
|
$commits[$gist->getType()] += $gist->getCommits();
|
||||||
$count = count($gistService->getHistory($gist));
|
|
||||||
$commits[$gist->getType()] += $count;
|
|
||||||
} catch(GitException $e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$output->writeln(['<comment>Gists statistics</comment>', '']);
|
$output->writeln(['<comment>Gists statistics</comment>', '']);
|
||||||
|
|
|
@ -7,6 +7,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class UpdateCommand.
|
* class UpdateCommand.
|
||||||
|
@ -26,8 +27,9 @@ class UpdateCommand extends Command
|
||||||
->setDescription('Update a gist using the API')
|
->setDescription('Update a gist using the API')
|
||||||
->addArgument('input', InputArgument::REQUIRED, 'Input')
|
->addArgument('input', InputArgument::REQUIRED, 'Input')
|
||||||
->addOption('gist', null, InputOption::VALUE_REQUIRED, 'Id or File of the gist')
|
->addOption('gist', null, InputOption::VALUE_REQUIRED, 'Id or File of the gist')
|
||||||
->addOption('show-url', 'u', InputOption::VALUE_NONE, 'Display only the gist url')
|
->addOption('all', 'a', InputOption::VALUE_NONE, 'Display all the response')
|
||||||
->addOption('show-id', 'i', InputOption::VALUE_NONE, 'Display only the gist Id')
|
->addOption('id', 'i', InputOption::VALUE_NONE, 'Display only the id of the gist')
|
||||||
|
->addOption('json', 'j', InputOption::VALUE_NONE, 'Format the response to json')
|
||||||
->setHelp(<<<EOF
|
->setHelp(<<<EOF
|
||||||
Provides a client to create a gist using the API.
|
Provides a client to create a gist using the API.
|
||||||
|
|
||||||
|
@ -43,11 +45,14 @@ Options:
|
||||||
<info>--gist</info>
|
<info>--gist</info>
|
||||||
Defines the Gist to update by using its Id or its File
|
Defines the Gist to update by using its Id or its File
|
||||||
|
|
||||||
<info>--show-id</info>, <info>-i</info>
|
<info>--id</info>, <info>-i</info>
|
||||||
Display only the Id of the gist
|
Display only the id of the gist
|
||||||
|
|
||||||
<info>--show-url</info>, <info>-u</info>
|
<info>--all</info>, <info>-a</info>
|
||||||
Display only the url of the gist
|
Display all the response
|
||||||
|
|
||||||
|
<info>--json</info>, <info>-j</info>
|
||||||
|
Format the response to json
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -57,10 +62,9 @@ EOF
|
||||||
*/
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
//$output->writeln(sprintf('<comment>%s</comment> bar.', 'test'));
|
|
||||||
|
|
||||||
$file = $input->getArgument('input');
|
$file = $input->getArgument('input');
|
||||||
$gist = $input->getOption('gist');
|
$gist = $input->getOption('gist');
|
||||||
|
$json = $input->getOption('json');
|
||||||
|
|
||||||
if ($file === '-') {
|
if ($file === '-') {
|
||||||
$content = file_get_contents('php://stdin');
|
$content = file_get_contents('php://stdin');
|
||||||
|
@ -86,19 +90,17 @@ EOF
|
||||||
|
|
||||||
$gist = $this->getSilexApplication()['api_client']->update($gist, $content);
|
$gist = $this->getSilexApplication()['api_client']->update($gist, $content);
|
||||||
|
|
||||||
if ($input->getOption('show-url')) {
|
if ($input->getOption('id')) {
|
||||||
$output->writeln($gist['url']);
|
$id = isset($gist['gist']['id']) ? $gist['gist']['id'] : $gist['gist']['Id'];
|
||||||
|
$result = $json ? json_encode(array('id' => $id)) : $id;
|
||||||
return true;
|
} elseif ($input->getOption('all')) {
|
||||||
|
$result = $json ? json_encode($gist) : Yaml::dump($gist);
|
||||||
|
} else {
|
||||||
|
$url = $gist['url'];
|
||||||
|
$result = $json ? json_encode(array('url' => $url)) : $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($input->getOption('show-id')) {
|
$output->writeln($result);
|
||||||
$output->writeln($gist['gist']['Id']);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$output->writeln(json_encode($gist));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
211
src/Gist/Composer/PostInstallHandler.php
Normal file
211
src/Gist/Composer/PostInstallHandler.php
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Gist\Composer;
|
||||||
|
|
||||||
|
use Symfony\Component\Process\PhpExecutableFinder;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
use Composer\Script\Event;
|
||||||
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||||
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||||
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
|
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||||
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
|
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||||
|
use Symfony\Component\Console\Question\Question;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class PostInstallHandler.
|
||||||
|
*
|
||||||
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
|
*/
|
||||||
|
class PostInstallHandler
|
||||||
|
{
|
||||||
|
public static function execute(Event $event)
|
||||||
|
{
|
||||||
|
$helper = new QuestionHelper();
|
||||||
|
$input = new ArgvInput();
|
||||||
|
$output = new ConsoleOutput();
|
||||||
|
$filesystem = new Filesystem();
|
||||||
|
|
||||||
|
$output->writeln('+==============================+');
|
||||||
|
$output->writeln('| GIST Setup |');
|
||||||
|
$output->writeln('+==============================+');
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln('1. Database');
|
||||||
|
$output->writeln('===========');
|
||||||
|
|
||||||
|
$configure = true;
|
||||||
|
if ($filesystem->exists('propel.yaml')) {
|
||||||
|
$output->writeln('The configuration file exists.');
|
||||||
|
$question = new ConfirmationQuestion('Your current configuration will not be merged. Do you want to override it? [y/N] ', false);
|
||||||
|
$configure = $helper->ask($input, $output, $question);
|
||||||
|
} else {
|
||||||
|
$configure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($configure) {
|
||||||
|
$choices = ['MySQL/MariaDB', 'SQLite', 'other'];
|
||||||
|
$question = new ChoiceQuestion('Which DBMS? ', $choices, 0);
|
||||||
|
$dbms = $helper->ask($input, $output, $question);
|
||||||
|
$substitutions = [];
|
||||||
|
|
||||||
|
if ($dbms === 'MySQL/MariaDB') {
|
||||||
|
$templateName = 'propel.yaml.dist-mysql';
|
||||||
|
|
||||||
|
$question = new Question('Host: [127.0.0.1] ', '127.0.0.1');
|
||||||
|
$substitutions['DATABASE_HOST'] = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new Question('Database (it must exists!): [gist] ', 'gist');
|
||||||
|
$substitutions['DATABASE_NAME'] = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new Question('Username: [root] ', 'root');
|
||||||
|
$substitutions['DATABASE_USERNAME'] = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new Question('Password: [] ', '');
|
||||||
|
$substitutions['DATABASE_PASSWORD'] = $helper->ask($input, $output, $question);
|
||||||
|
} elseif ($dbms === 'SQLite') {
|
||||||
|
$defaultPath = getcwd().'/data/gist.sqlite';
|
||||||
|
$question = new Question("Ok! Where do you want me to save datas? [$defaultPath] ", $defaultPath);
|
||||||
|
$substitutions['DATABASE_PATH'] = $helper->ask($input, $output, $question);
|
||||||
|
$templateName = 'propel.yaml.dist-sqlite';
|
||||||
|
} else {
|
||||||
|
$output->writeln('See README.md to perform the configuration.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$template = file_get_contents('app/config/'.$templateName);
|
||||||
|
$content = str_replace(
|
||||||
|
array_keys($substitutions),
|
||||||
|
array_values($substitutions),
|
||||||
|
$template
|
||||||
|
);
|
||||||
|
|
||||||
|
$done = file_put_contents('propel.yaml', $content) !== false;
|
||||||
|
|
||||||
|
if ($done) {
|
||||||
|
$output->writeln('Running migration...');
|
||||||
|
|
||||||
|
foreach (['config:convert', 'model:build --recursive', 'migration:diff --recursive', 'migration:migrate --recursive'] as $arg) {
|
||||||
|
$command = self::getPhp(true).' ./vendor/propel/propel/bin/propel '.$arg;
|
||||||
|
$process = new Process($command);
|
||||||
|
$process->run();
|
||||||
|
|
||||||
|
if (!$process->isSuccessful()) {
|
||||||
|
$output->writeln('An error occured while executing:');
|
||||||
|
$output->writeln($command);
|
||||||
|
$output->writeln('To perform the configuration. See README.md.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->writeln('Done!');
|
||||||
|
} else {
|
||||||
|
$output->writeln('An error occured. See README.md to perform the configuration.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln('2. Application');
|
||||||
|
$output->writeln('==============');
|
||||||
|
|
||||||
|
$configure = true;
|
||||||
|
if ($filesystem->exists('app/config/config.yml')) {
|
||||||
|
$output->writeln('The configuration file exists.');
|
||||||
|
$question = new ConfirmationQuestion('Your current configuration will not be merged. Do you want to override it? [y/N] ', false);
|
||||||
|
$configure = $helper->ask($input, $output, $question);
|
||||||
|
} else {
|
||||||
|
$configure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($configure) {
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln(' 2.1 Security');
|
||||||
|
$output->writeln('-------------');
|
||||||
|
|
||||||
|
$token = str_shuffle(sha1(microtime().uniqid()));
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion('Registration enabled: [Y/n] ', true);
|
||||||
|
$enableRegistration = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion('Login enabled: [Y/n] ', true);
|
||||||
|
$enableLogin = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion('Login required to edit a gist: [y/N] ', false);
|
||||||
|
$loginRequiredToEditGist = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion('Login required to view a gist: [y/N] ', false);
|
||||||
|
$loginRequiredToViewGist = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion('Login required to view an embeded gist: [y/N] ', false);
|
||||||
|
$loginRequiredToViewEmbededGist = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln(' 2.2 API');
|
||||||
|
$output->writeln('--------');
|
||||||
|
|
||||||
|
$question = new ConfirmationQuestion('API enabled: [Y/n] ', true);
|
||||||
|
$apiEnabled = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
if ($apiEnabled) {
|
||||||
|
$question = new ConfirmationQuestion('API key required: [y/N] ', false);
|
||||||
|
$apikeyRequired = $helper->ask($input, $output, $question);
|
||||||
|
} else {
|
||||||
|
$apikeyRequired = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$question = new Question('[Client] API base URL: [https://gist.deblan.org/] ', 'https://gist.deblan.org/');
|
||||||
|
$apiBaseUrl = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$question = new Question('[Client] API key: [] ', '');
|
||||||
|
$apiClientApiKey = $helper->ask($input, $output, $question);
|
||||||
|
|
||||||
|
$configuration = [
|
||||||
|
'security' => [
|
||||||
|
'token' => $token,
|
||||||
|
'enable_registration' => $enableRegistration,
|
||||||
|
'enable_login' => $enableLogin,
|
||||||
|
'login_required_to_edit_gist' => $loginRequiredToEditGist,
|
||||||
|
'login_required_to_view_gist' => $loginRequiredToViewGist,
|
||||||
|
'login_required_to_view_embeded_gist' => $loginRequiredToViewEmbededGist,
|
||||||
|
],
|
||||||
|
'api' => [
|
||||||
|
'enabled' => $apiEnabled,
|
||||||
|
'api_key_required' => $apikeyRequired,
|
||||||
|
'base_url' => $apiBaseUrl,
|
||||||
|
'client' => [
|
||||||
|
'api_key' => $apiClientApiKey,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'data' => [
|
||||||
|
'path' => 'data/git',
|
||||||
|
],
|
||||||
|
'git' => [
|
||||||
|
'path' => '/usr/bin/git',
|
||||||
|
],
|
||||||
|
'theme' => [
|
||||||
|
'name' => 'dark',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$content = (new Yaml())->dump($configuration);
|
||||||
|
|
||||||
|
$done = file_put_contents('app/config/config.yml', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->writeln('');
|
||||||
|
$output->writeln('Configuration finished!');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function getPhp($includeArgs = true)
|
||||||
|
{
|
||||||
|
$phpFinder = new PhpExecutableFinder();
|
||||||
|
if (!$phpPath = $phpFinder->find($includeArgs)) {
|
||||||
|
throw new \RuntimeException('The php executable could not be found, add it to your PATH environment variable and try again');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $phpPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,9 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Gist\Form\ApiCreateGistForm;
|
use Gist\Form\ApiCreateGistForm;
|
||||||
use Gist\Model\GistQuery;
|
use Gist\Model\GistQuery;
|
||||||
use Gist\Form\ApiUpdateGistForm;
|
use Gist\Form\ApiUpdateGistForm;
|
||||||
|
use GitWrapper\GitException;
|
||||||
|
use Gist\Model\UserQuery;
|
||||||
|
use Propel\Runtime\ActiveQuery\Criteria;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ApiController.
|
* Class ApiController.
|
||||||
|
@ -16,10 +19,80 @@ use Gist\Form\ApiUpdateGistForm;
|
||||||
*/
|
*/
|
||||||
class ApiController extends Controller
|
class ApiController extends Controller
|
||||||
{
|
{
|
||||||
public function createAction(Request $request)
|
/**
|
||||||
|
* Lists gists.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $apiKey
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function listAction(Request $request, $apiKey)
|
||||||
{
|
{
|
||||||
$app = $this->getApp();
|
$app = $this->getApp();
|
||||||
|
|
||||||
|
if (false === $app['settings']['api']['enabled']) {
|
||||||
|
return new Response('', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isValidApiKey($apiKey, true)) {
|
||||||
|
return $this->invalidApiKeyResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $request->isMethod('get')) {
|
||||||
|
return $this->invalidMethodResponse('GET method is required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $app['user.provider']->loadUserByApiKey($apiKey);
|
||||||
|
|
||||||
|
$criteria = GistQuery::create()
|
||||||
|
->limit(15)
|
||||||
|
->orderById(Criteria::DESC);
|
||||||
|
|
||||||
|
$gists = $user->getGists($criteria);
|
||||||
|
$data = array();
|
||||||
|
|
||||||
|
foreach ($gists as $gist) {
|
||||||
|
try {
|
||||||
|
$history = $app['gist']->getHistory($gist);
|
||||||
|
|
||||||
|
$value = $gist->toArray();
|
||||||
|
$value['url'] = $request->getSchemeAndHttpHost().$app['url_generator']->generate(
|
||||||
|
'view',
|
||||||
|
array(
|
||||||
|
'gist' => $gist->getFile(),
|
||||||
|
'commit' => array_pop($history)['commit'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$data[] = $value;
|
||||||
|
} catch (GitException $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonResponse($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a gist.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $apiKey
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function createAction(Request $request, $apiKey)
|
||||||
|
{
|
||||||
|
$app = $this->getApp();
|
||||||
|
|
||||||
|
if (false === $app['settings']['api']['enabled']) {
|
||||||
|
return new Response('', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isValidApiKey($apiKey, (bool) $app['settings']['api']['api_key_required'])) {
|
||||||
|
return $this->invalidApiKeyResponse();
|
||||||
|
}
|
||||||
|
|
||||||
if (false === $request->isMethod('post')) {
|
if (false === $request->isMethod('post')) {
|
||||||
return $this->invalidMethodResponse('POST method is required.');
|
return $this->invalidMethodResponse('POST method is required.');
|
||||||
}
|
}
|
||||||
|
@ -36,40 +109,65 @@ class ApiController extends Controller
|
||||||
$form->submit($request);
|
$form->submit($request);
|
||||||
|
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
|
$user = !empty($apiKey) ? $app['user.provider']->loadUserByApiKey($apiKey) : null;
|
||||||
$gist = $app['gist']->create(new Gist(), $form->getData());
|
$gist = $app['gist']->create(new Gist(), $form->getData());
|
||||||
$gist->setCipher(false)->save();
|
$gist
|
||||||
|
->setCipher(false)
|
||||||
|
->setUser($user)
|
||||||
|
->save();
|
||||||
|
|
||||||
$history = $app['gist']->getHistory($gist);
|
$history = $app['gist']->getHistory($gist);
|
||||||
|
|
||||||
return new JsonResponse(array(
|
$data = $gist->toArray();
|
||||||
'url' => $request->getSchemeAndHttpHost().$app['url_generator']->generate(
|
$data['url'] = $request->getSchemeAndHttpHost().$app['url_generator']->generate(
|
||||||
'view',
|
'view',
|
||||||
array(
|
array(
|
||||||
'gist' => $gist->getFile(),
|
'gist' => $gist->getFile(),
|
||||||
'commit' => array_pop($history)['commit'],
|
'commit' => array_pop($history)['commit'],
|
||||||
)
|
)
|
||||||
),
|
);
|
||||||
'gist' => $gist->toArray(),
|
|
||||||
));
|
return new JsonResponse($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->invalidRequestResponse('Invalid field(s)');
|
return $this->invalidRequestResponse('Invalid field(s)');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateAction(Request $request, $gist)
|
/**
|
||||||
|
* Updates a gist.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $gist
|
||||||
|
* @param string $apiKey
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function updateAction(Request $request, $gist, $apiKey)
|
||||||
{
|
{
|
||||||
$app = $this->getApp();
|
$app = $this->getApp();
|
||||||
|
|
||||||
|
if (false === $app['settings']['api']['enabled']) {
|
||||||
|
return new Response('', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isValidApiKey($apiKey, (bool) $app['settings']['api']['api_key_required'])) {
|
||||||
|
return $this->invalidApiKeyResponse();
|
||||||
|
}
|
||||||
|
|
||||||
if (false === $request->isMethod('post')) {
|
if (false === $request->isMethod('post')) {
|
||||||
return $this->invalidMethodResponse('POST method is required.');
|
return $this->invalidMethodResponse('POST method is required.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$gist = GistQuery::create()
|
$query = GistQuery::create()
|
||||||
->filterByCipher(false)
|
->filterByCipher(false);
|
||||||
->filterById((int) $gist)
|
|
||||||
->_or()
|
if (ctype_digit($gist)) {
|
||||||
->filterByFile($gist)
|
$query->filterById((int) $gist);
|
||||||
->findOne();
|
} else {
|
||||||
|
$query->filterByFile($gist);
|
||||||
|
}
|
||||||
|
|
||||||
|
$gist = $query->findOne();
|
||||||
|
|
||||||
if (!$gist) {
|
if (!$gist) {
|
||||||
return $this->invalidRequestResponse('Invalid Gist');
|
return $this->invalidRequestResponse('Invalid Gist');
|
||||||
|
@ -91,21 +189,88 @@ class ApiController extends Controller
|
||||||
|
|
||||||
$history = $app['gist']->getHistory($gist);
|
$history = $app['gist']->getHistory($gist);
|
||||||
|
|
||||||
return new JsonResponse(array(
|
$data = $gist->toArray();
|
||||||
'url' => $request->getSchemeAndHttpHost().$app['url_generator']->generate(
|
$data['url'] = $request->getSchemeAndHttpHost().$app['url_generator']->generate(
|
||||||
'view',
|
'view',
|
||||||
array(
|
array(
|
||||||
'gist' => $gist->getFile(),
|
'gist' => $gist->getFile(),
|
||||||
'commit' => array_pop($history)['commit'],
|
'commit' => array_pop($history)['commit'],
|
||||||
)
|
)
|
||||||
),
|
);
|
||||||
'gist' => $gist->toArray(),
|
|
||||||
));
|
return new JsonResponse($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->invalidRequestResponse('Invalid field(s)');
|
return $this->invalidRequestResponse('Invalid field(s)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a gist.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $gist
|
||||||
|
* @param string $apiKey
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function deleteAction(Request $request, $gist, $apiKey)
|
||||||
|
{
|
||||||
|
$app = $this->getApp();
|
||||||
|
|
||||||
|
if (false === $app['settings']['api']['enabled']) {
|
||||||
|
return new Response('', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isValidApiKey($apiKey, true)) {
|
||||||
|
return $this->invalidApiKeyResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $request->isMethod('post')) {
|
||||||
|
return $this->invalidMethodResponse('POST method is required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $app['user.provider']->loadUserByApiKey($apiKey);
|
||||||
|
|
||||||
|
$gist = GistQuery::create()
|
||||||
|
->filterById((int) $gist)
|
||||||
|
->_or()
|
||||||
|
->filterByFile($gist)
|
||||||
|
->filterByUser($user)
|
||||||
|
->findOne();
|
||||||
|
|
||||||
|
if (!$gist) {
|
||||||
|
return $this->invalidRequestResponse('Invalid Gist');
|
||||||
|
}
|
||||||
|
|
||||||
|
$gist->delete();
|
||||||
|
|
||||||
|
return new JsonResponse(['error' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an invalid api key response.
|
||||||
|
*
|
||||||
|
* @param mixed $message
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
protected function invalidApiKeyResponse()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'error' => ' Unauthorized',
|
||||||
|
'message' => 'Invalid API KEY',
|
||||||
|
];
|
||||||
|
|
||||||
|
return new JsonResponse($data, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an invalid method response.
|
||||||
|
*
|
||||||
|
* @param mixed $message
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
protected function invalidMethodResponse($message = null)
|
protected function invalidMethodResponse($message = null)
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -116,6 +281,13 @@ class ApiController extends Controller
|
||||||
return new JsonResponse($data, 405);
|
return new JsonResponse($data, 405);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an invalid request response.
|
||||||
|
*
|
||||||
|
* @param mixed $message
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
protected function invalidRequestResponse($message = null)
|
protected function invalidRequestResponse($message = null)
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -125,4 +297,24 @@ class ApiController extends Controller
|
||||||
|
|
||||||
return new JsonResponse($data, 400);
|
return new JsonResponse($data, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given api key is valid
|
||||||
|
* depending of the requirement.
|
||||||
|
*
|
||||||
|
* @param mixed $apiKey
|
||||||
|
* @param mixed $required
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isValidApiKey($apiKey, $required = false)
|
||||||
|
{
|
||||||
|
if (empty($apiKey)) {
|
||||||
|
return !$required;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UserQuery::create()
|
||||||
|
->filterByApiKey($apiKey)
|
||||||
|
->count() === 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,34 @@ use Symfony\Component\HttpFoundation\Response;
|
||||||
*
|
*
|
||||||
* @author Simon Vieille <simon@deblan.fr>
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
*/
|
*/
|
||||||
class Controller
|
abstract class Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Application
|
* @var Application
|
||||||
*/
|
*/
|
||||||
protected $app;
|
protected $app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $types = [
|
||||||
|
'html',
|
||||||
|
'css',
|
||||||
|
'javascript',
|
||||||
|
'php',
|
||||||
|
'sql',
|
||||||
|
'xml',
|
||||||
|
'yaml',
|
||||||
|
'markdown',
|
||||||
|
'perl',
|
||||||
|
'c',
|
||||||
|
'asp',
|
||||||
|
'python',
|
||||||
|
'bash',
|
||||||
|
'actionscript3',
|
||||||
|
'text',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __construct.
|
* __construct.
|
||||||
*
|
*
|
||||||
|
@ -88,10 +109,10 @@ class Controller
|
||||||
return array(
|
return array(
|
||||||
'gist' => $gist,
|
'gist' => $gist,
|
||||||
'type' => $gist->getType(),
|
'type' => $gist->getType(),
|
||||||
|
'types' => $this->types,
|
||||||
'history' => $history,
|
'history' => $history,
|
||||||
'commit' => $commit,
|
'commit' => $commit,
|
||||||
'raw_content' => $content,
|
'raw_content' => $content,
|
||||||
'content' => $app['gist']->highlight($gist->getGeshiType(), $content),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +149,17 @@ class Controller
|
||||||
/**
|
/**
|
||||||
* Returns the connected user.
|
* Returns the connected user.
|
||||||
*
|
*
|
||||||
|
* @param Request $request An API request
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getUser()
|
public function getUser(Request $request = null)
|
||||||
{
|
{
|
||||||
$app = $this->getApp();
|
$app = $this->getApp();
|
||||||
|
|
||||||
|
if (!empty($request)) {
|
||||||
|
}
|
||||||
|
|
||||||
$securityContext = $app['security.token_storage'];
|
$securityContext = $app['security.token_storage'];
|
||||||
$securityToken = $securityContext->getToken();
|
$securityToken = $securityContext->getToken();
|
||||||
|
|
||||||
|
@ -175,4 +201,32 @@ class Controller
|
||||||
$params
|
$params
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Response.
|
||||||
|
*
|
||||||
|
* @param string $template
|
||||||
|
* @param array $params
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function createResponse($template, array $params = null)
|
||||||
|
{
|
||||||
|
$body = $this->render($template, $params);
|
||||||
|
|
||||||
|
$response = new Response($body);
|
||||||
|
|
||||||
|
if (empty($params['no_cache'])) {
|
||||||
|
$ttl = 3600 * 24 * 7;
|
||||||
|
$etag = sha1($response->getContent());
|
||||||
|
|
||||||
|
$response->setTtl($ttl);
|
||||||
|
$response->setClientTtl($ttl);
|
||||||
|
$response->setExpires(new \DateTime('now +7 days'));
|
||||||
|
$response->setLastModified(new \DateTime('now'));
|
||||||
|
$response->setEtag($etag, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ use Gist\Form\CloneGistForm;
|
||||||
use Gist\Model\Gist;
|
use Gist\Model\Gist;
|
||||||
use GitWrapper\GitException;
|
use GitWrapper\GitException;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\Form\FormError;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class EditController.
|
* Class EditController.
|
||||||
|
@ -21,7 +23,7 @@ class EditController extends Controller
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function createAction(Request $request)
|
public function createAction(Request $request)
|
||||||
{
|
{
|
||||||
|
@ -37,17 +39,28 @@ class EditController extends Controller
|
||||||
|
|
||||||
if ($request->isMethod('post')) {
|
if ($request->isMethod('post')) {
|
||||||
$form->submit($request);
|
$form->submit($request);
|
||||||
|
$data = $form->getData();
|
||||||
|
|
||||||
|
if (empty($form->getData()['content']) && $form->get('file')->getData()) {
|
||||||
|
$data['content'] = file_get_contents($form->get('file')->getData()->getPathName());
|
||||||
|
unset($data['file']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($data['content'])) {
|
||||||
|
$form->get('content')->addError(new FormError($app['translator']->trans('form.error.not_blank')));
|
||||||
|
}
|
||||||
|
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$gist = $app['gist']->create(new Gist(), $form->getData(), $this->getUser());
|
$gist = $app['gist']->create(new Gist(), $data, $this->getUser());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render(
|
return $this->createResponse(
|
||||||
'Edit/index.html.twig',
|
'Edit/index.html.twig',
|
||||||
array(
|
array(
|
||||||
'gist' => isset($gist) ? $gist : null,
|
'gist' => isset($gist) ? $gist : null,
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
|
'no_cache' => true,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +70,7 @@ class EditController extends Controller
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function cloneAction(Request $request, $gist, $commit)
|
public function cloneAction(Request $request, $gist, $commit)
|
||||||
{
|
{
|
||||||
|
@ -97,7 +110,8 @@ class EditController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
$viewOptions['form'] = $form->createView();
|
$viewOptions['form'] = $form->createView();
|
||||||
|
$viewOptions['no_cache'] = true;
|
||||||
|
|
||||||
return $this->render('Edit/clone.html.twig', $viewOptions);
|
return $this->createResponse('Edit/clone.html.twig', $viewOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,13 @@ class LoginController extends Controller
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function registerAction(Request $request)
|
public function registerAction(Request $request)
|
||||||
{
|
{
|
||||||
$app = $this->getApp();
|
$app = $this->getApp();
|
||||||
|
|
||||||
if (false === $app['enable_registration']) {
|
if (false === $app['settings']['security']['enable_registration']) {
|
||||||
return new Response('', 403);
|
return new Response('', 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +57,13 @@ class LoginController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render(
|
return $this->createResponse(
|
||||||
'Login/register.html.twig',
|
'Login/register.html.twig',
|
||||||
[
|
[
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
'error' => isset($error) ? $error : '',
|
'error' => isset($error) ? $error : '',
|
||||||
'success' => isset($success) ? $success : '',
|
'success' => isset($success) ? $success : '',
|
||||||
|
'no_cache' => true,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -72,13 +73,13 @@ class LoginController extends Controller
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function loginAction(Request $request)
|
public function loginAction(Request $request)
|
||||||
{
|
{
|
||||||
$app = $this->getApp();
|
$app = $this->getApp();
|
||||||
|
|
||||||
if (false === $app['enable_login']) {
|
if (false === $app['settings']['security']['enable_login']) {
|
||||||
return new Response('', 403);
|
return new Response('', 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +98,12 @@ class LoginController extends Controller
|
||||||
$error = $app['translator']->trans('login.login.invalid');
|
$error = $app['translator']->trans('login.login.invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render(
|
return $this->createResponse(
|
||||||
'Login/login.html.twig',
|
'Login/login.html.twig',
|
||||||
[
|
[
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
'error' => isset($error) ? $error : '',
|
'error' => isset($error) ? $error : '',
|
||||||
|
'no_cache' => true,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use Gist\Form\DeleteGistForm;
|
||||||
use Gist\Form\FilterGistForm;
|
use Gist\Form\FilterGistForm;
|
||||||
use Gist\Form\UserPasswordForm;
|
use Gist\Form\UserPasswordForm;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class MyController.
|
* Class MyController.
|
||||||
|
@ -21,7 +22,7 @@ class MyController extends Controller
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param int $page
|
* @param int $page
|
||||||
*
|
*
|
||||||
* @return string
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function myAction(Request $request, $page)
|
public function myAction(Request $request, $page)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +59,26 @@ class MyController extends Controller
|
||||||
|
|
||||||
$gists = $this->getUser()->getGistsPager($page, $options);
|
$gists = $this->getUser()->getGistsPager($page, $options);
|
||||||
|
|
||||||
|
$apiKey = $this->getUser()->getApiKey();
|
||||||
|
|
||||||
|
if (empty($apiKey)) {
|
||||||
|
$regenerateApiKey = true;
|
||||||
|
}
|
||||||
|
// FIXME: CSRF issue!
|
||||||
|
elseif ($request->request->get('apiKey') === $apiKey && $request->request->has('generateApiKey')) {
|
||||||
|
$regenerateApiKey = true;
|
||||||
|
} else {
|
||||||
|
$regenerateApiKey = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($regenerateApiKey) {
|
||||||
|
$apiKey = $app['salt_generator']->generate(32, true);
|
||||||
|
|
||||||
|
$this->getUser()
|
||||||
|
->setApiKey($apiKey)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->isMethod('post')) {
|
if ($request->isMethod('post')) {
|
||||||
$deleteForm->handleRequest($request);
|
$deleteForm->handleRequest($request);
|
||||||
$passwordForm->handleRequest($request);
|
$passwordForm->handleRequest($request);
|
||||||
|
@ -99,15 +120,17 @@ class MyController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render(
|
return $this->createResponse(
|
||||||
'My/my.html.twig',
|
'My/my.html.twig',
|
||||||
array(
|
array(
|
||||||
'gists' => $gists,
|
'gists' => $gists,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
|
'apiKey' => $apiKey,
|
||||||
'deleteForm' => $deleteForm->createView(),
|
'deleteForm' => $deleteForm->createView(),
|
||||||
'filterForm' => $filterForm->createView(),
|
'filterForm' => $filterForm->createView(),
|
||||||
'passwordForm' => $passwordForm->createView(),
|
'passwordForm' => $passwordForm->createView(),
|
||||||
'deleted' => !empty($deleted),
|
'deleted' => !empty($deleted),
|
||||||
|
'no_cache' => true,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,18 @@ class ViewController extends Controller
|
||||||
$viewOptions = $this->getViewOptions($request, $gist, $commit);
|
$viewOptions = $this->getViewOptions($request, $gist, $commit);
|
||||||
|
|
||||||
if (is_array($viewOptions)) {
|
if (is_array($viewOptions)) {
|
||||||
return $this->render('View/view.html.twig', $viewOptions);
|
if ($request->query->has('type')) {
|
||||||
|
$type = $request->query->get('type');
|
||||||
|
|
||||||
|
if (in_array($type, $this->types)) {
|
||||||
|
$viewOptions['gist']->setType($type);
|
||||||
|
$viewOptions['type_overrided'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$viewOptions['no_cache'] = true;
|
||||||
|
|
||||||
|
return $this->createResponse('View/view.html.twig', $viewOptions);
|
||||||
} else {
|
} else {
|
||||||
return $this->notFoundResponse();
|
return $this->notFoundResponse();
|
||||||
}
|
}
|
||||||
|
@ -53,7 +64,16 @@ class ViewController extends Controller
|
||||||
$viewOptions = $this->getViewOptions($request, $gist, $commit);
|
$viewOptions = $this->getViewOptions($request, $gist, $commit);
|
||||||
|
|
||||||
if (is_array($viewOptions)) {
|
if (is_array($viewOptions)) {
|
||||||
return $app['twig']->render('View/embed.html.twig', $viewOptions);
|
if ($request->query->has('type')) {
|
||||||
|
$type = $request->query->get('type');
|
||||||
|
|
||||||
|
if (in_array($type, $this->types)) {
|
||||||
|
$viewOptions['gist']->setType($type);
|
||||||
|
$viewOptions['type_overrided'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->createResponse('View/embed.html.twig', $viewOptions);
|
||||||
} else {
|
} else {
|
||||||
return $this->notFoundResponse();
|
return $this->notFoundResponse();
|
||||||
}
|
}
|
||||||
|
@ -66,19 +86,25 @@ class ViewController extends Controller
|
||||||
* @param string $gist Gist's ID
|
* @param string $gist Gist's ID
|
||||||
* @param string $commit The commit
|
* @param string $commit The commit
|
||||||
*
|
*
|
||||||
* @return string|Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function embedJsAction(Request $request, $gist, $commit)
|
public function embedJsAction(Request $request, $gist, $commit)
|
||||||
{
|
{
|
||||||
$viewOptions = $this->getViewOptions($request, $gist, $commit);
|
$viewOptions = $this->getViewOptions($request, $gist, $commit);
|
||||||
|
|
||||||
return new Response(
|
if ($request->query->has('type')) {
|
||||||
$this->render('View/embedJs.html.twig', $viewOptions),
|
$type = $request->query->get('type');
|
||||||
200,
|
|
||||||
array(
|
if (in_array($type, $this->types)) {
|
||||||
'Content-Type' => 'text/javascript',
|
$viewOptions['gist']->setType($type);
|
||||||
)
|
$viewOptions['type_overrided'] = true;
|
||||||
);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->createResponse('View/embedJs.html.twig', $viewOptions);
|
||||||
|
$response->headers->set('Content-Type', 'text/javascript');
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +114,7 @@ class ViewController extends Controller
|
||||||
* @param string $gist Gist's ID
|
* @param string $gist Gist's ID
|
||||||
* @param string $commit The commit
|
* @param string $commit The commit
|
||||||
*
|
*
|
||||||
* @return string|Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function rawAction(Request $request, $gist, $commit)
|
public function rawAction(Request $request, $gist, $commit)
|
||||||
{
|
{
|
||||||
|
@ -114,7 +140,7 @@ class ViewController extends Controller
|
||||||
* @param string $gist Gist's ID
|
* @param string $gist Gist's ID
|
||||||
* @param string $commit The commit
|
* @param string $commit The commit
|
||||||
*
|
*
|
||||||
* @return string|Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function downloadAction(Request $request, $gist, $commit)
|
public function downloadAction(Request $request, $gist, $commit)
|
||||||
{
|
{
|
||||||
|
@ -131,9 +157,10 @@ class ViewController extends Controller
|
||||||
200,
|
200,
|
||||||
array(
|
array(
|
||||||
'Content-Disposition' => sprintf('filename=%s.%s', $gist->getFile(), $gist->getTypeAsExtension()),
|
'Content-Disposition' => sprintf('filename=%s.%s', $gist->getFile(), $gist->getTypeAsExtension()),
|
||||||
'Content-Length' => filesize($file),
|
'Content-Length' => mb_strlen($viewOptions['raw_content']),
|
||||||
'Content-Type' => 'application/force-download',
|
'Content-Type' => 'application/force-download',
|
||||||
)
|
),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return $this->notFoundResponse($app);
|
return $this->notFoundResponse($app);
|
||||||
|
@ -146,7 +173,7 @@ class ViewController extends Controller
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param string $gist Gist's ID
|
* @param string $gist Gist's ID
|
||||||
*
|
*
|
||||||
* @return string|Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function revisionsAction(Request $request, $gist)
|
public function revisionsAction(Request $request, $gist)
|
||||||
{
|
{
|
||||||
|
@ -164,7 +191,7 @@ class ViewController extends Controller
|
||||||
return $this->notFoundResponse();
|
return $this->notFoundResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render(
|
return $this->createResponse(
|
||||||
'View/revisions.html.twig',
|
'View/revisions.html.twig',
|
||||||
array(
|
array(
|
||||||
'gist' => $gist,
|
'gist' => $gist,
|
||||||
|
|
|
@ -16,7 +16,9 @@ class ApiCreateGistForm extends CreateGistForm
|
||||||
{
|
{
|
||||||
parent::build($options);
|
parent::build($options);
|
||||||
|
|
||||||
$this->builder->remove('cipher');
|
$this->builder
|
||||||
|
->remove('cipher')
|
||||||
|
->remove('file');
|
||||||
|
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ class ApiUpdateGistForm extends ApiCreateGistForm
|
||||||
|
|
||||||
$this->builder
|
$this->builder
|
||||||
->remove('title')
|
->remove('title')
|
||||||
|
->remove('file')
|
||||||
->remove('type');
|
->remove('type');
|
||||||
|
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
|
|
|
@ -32,16 +32,25 @@ class CreateGistForm extends AbstractForm
|
||||||
'content',
|
'content',
|
||||||
'textarea',
|
'textarea',
|
||||||
array(
|
array(
|
||||||
'required' => true,
|
'required' => false,
|
||||||
'attr' => array(
|
'attr' => array(
|
||||||
'class' => 'form-control',
|
'class' => 'form-control',
|
||||||
'rows' => 10,
|
'rows' => 10,
|
||||||
),
|
),
|
||||||
'trim' => false,
|
'trim' => false,
|
||||||
'constraints' => array(
|
'constraints' => array(
|
||||||
new NotBlank(array(
|
),
|
||||||
'message' => $this->translator->trans('form.error.not_blank'),
|
)
|
||||||
)),
|
);
|
||||||
|
|
||||||
|
$this->builder->add(
|
||||||
|
'file',
|
||||||
|
'file',
|
||||||
|
array(
|
||||||
|
'required' => false,
|
||||||
|
'attr' => array(
|
||||||
|
),
|
||||||
|
'constraints' => array(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -88,6 +97,7 @@ class CreateGistForm extends AbstractForm
|
||||||
'sql' => '',
|
'sql' => '',
|
||||||
'xml' => '',
|
'xml' => '',
|
||||||
'yaml' => '',
|
'yaml' => '',
|
||||||
|
'markdown' => '',
|
||||||
'perl' => '',
|
'perl' => '',
|
||||||
'c' => '',
|
'c' => '',
|
||||||
'asp' => '',
|
'asp' => '',
|
||||||
|
|
|
@ -44,6 +44,18 @@ class FilterGistForm extends AbstractForm
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->builder->add(
|
||||||
|
'title',
|
||||||
|
'text',
|
||||||
|
array(
|
||||||
|
'required' => false,
|
||||||
|
'attr' => array(
|
||||||
|
'placeholder' => $this->translator->trans('form.title.placeholder'),
|
||||||
|
'class' => 'form-control',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$this->builder->setMethod('GET');
|
$this->builder->setMethod('GET');
|
||||||
|
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Gist\Model;
|
namespace Gist\Model;
|
||||||
|
|
||||||
use Gist\Model\Base\Gist as BaseGist;
|
use Gist\Model\Base\Gist as BaseGist;
|
||||||
|
use Propel\Runtime\Map\TableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Gist.
|
* Class Gist.
|
||||||
|
@ -44,14 +45,16 @@ class Gist extends BaseGist
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type for Geshi.
|
* Returns the type for highlighting.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getGeshiType()
|
public function getHighlightType()
|
||||||
{
|
{
|
||||||
$data = array(
|
$data = array(
|
||||||
'html' => 'xml',
|
'html' => 'xml',
|
||||||
|
'asp' => 'aspnet',
|
||||||
|
'actionscript3' => 'actionscript',
|
||||||
);
|
);
|
||||||
|
|
||||||
return str_replace(array_keys($data), array_values($data), $this->getType());
|
return str_replace(array_keys($data), array_values($data), $this->getType());
|
||||||
|
@ -72,8 +75,40 @@ class Gist extends BaseGist
|
||||||
'bash' => 'sh',
|
'bash' => 'sh',
|
||||||
'actionscript3' => 'as',
|
'actionscript3' => 'as',
|
||||||
'text' => 'txt',
|
'text' => 'txt',
|
||||||
|
'markdown' => 'md',
|
||||||
);
|
);
|
||||||
|
|
||||||
return str_replace(array_keys($data), array_values($data), $this->getType());
|
return str_replace(array_keys($data), array_values($data), $this->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increments the number of commits.
|
||||||
|
*/
|
||||||
|
public function commit()
|
||||||
|
{
|
||||||
|
$this->setCommits($this->getCommits() + 1);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function toArray($keyType = TableMap::TYPE_PHPNAME, $includeLazyLoadColumns = true, $alreadyDumpedObjects = array(), $includeForeignObjects = false)
|
||||||
|
{
|
||||||
|
$data = parent::toArray(
|
||||||
|
$keyType,
|
||||||
|
$includeLazyLoadColumns,
|
||||||
|
$alreadyDumpedObjects,
|
||||||
|
$includeForeignObjects
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
$newKey = lcfirst($key);
|
||||||
|
unset($data[$key]);
|
||||||
|
$data[$newKey] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,10 @@ class User extends BaseUser implements UserInterface
|
||||||
$query->filterByType($options['type']);
|
$query->filterByType($options['type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($options['title'])) {
|
||||||
|
$query->filterByTitle('%'.$options['title'].'%', Criteria::LIKE);
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($options['cipher']) && $options['cipher'] !== 'anyway') {
|
if (!empty($options['cipher']) && $options['cipher'] !== 'anyway') {
|
||||||
$bools = array(
|
$bools = array(
|
||||||
'yes' => true,
|
'yes' => true,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<column name="type" type="VARCHAR" size="30" required="true" />
|
<column name="type" type="VARCHAR" size="30" required="true" />
|
||||||
<column name="file" type="VARCHAR" size="30" required="true" />
|
<column name="file" type="VARCHAR" size="30" required="true" />
|
||||||
<column name="user_id" type="INTEGER" required="false" />
|
<column name="user_id" type="INTEGER" required="false" />
|
||||||
|
<column name="commits" type="INTEGER" required="true" defaultValue="0" />
|
||||||
|
|
||||||
<foreign-key foreignTable="user" onDelete="setnull" onUpdate="cascade">
|
<foreign-key foreignTable="user" onDelete="setnull" onUpdate="cascade">
|
||||||
<reference local="user_id" foreign="id"/>
|
<reference local="user_id" foreign="id"/>
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
<column name="password" type="VARCHAR" size="255" required="true" />
|
<column name="password" type="VARCHAR" size="255" required="true" />
|
||||||
<column name="roles" type="VARCHAR" size="255" required="true" />
|
<column name="roles" type="VARCHAR" size="255" required="true" />
|
||||||
<column name="salt" type="VARCHAR" size="64" required="true" />
|
<column name="salt" type="VARCHAR" size="64" required="true" />
|
||||||
|
<column name="api_key" type="VARCHAR" size="32" required="true" />
|
||||||
|
|
||||||
<behavior name="timestampable"/>
|
<behavior name="timestampable"/>
|
||||||
</table>
|
</table>
|
||||||
|
|
1
src/Gist/Resources/public
Symbolic link
1
src/Gist/Resources/public
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../web/app/
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<form action="{{ path('home') }}" method="post" id="main-form">
|
<form action="{{ path('home') }}" method="post" id="main-form" enctype="multipart/form-data">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
@ -71,6 +71,10 @@
|
||||||
{{ form_errors(form.content) }}
|
{{ form_errors(form.content) }}
|
||||||
{{ form_widget(form.content) }}
|
{{ form_widget(form.content) }}
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
{{ form_errors(form.file) }}
|
||||||
|
{{ form_widget(form.file) }}
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input type="submit" class="btn btn-primary" value="{{ 'form.submit'|trans }}">
|
<input type="submit" class="btn btn-primary" value="{{ 'form.submit'|trans }}">
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -45,7 +45,10 @@
|
||||||
|
|
||||||
{% set params = app.request.attributes.get('_route_params')|merge({page: 1}) %}
|
{% set params = app.request.attributes.get('_route_params')|merge({page: 1}) %}
|
||||||
|
|
||||||
<form action="{{ path('my', params) }}" method="GET">
|
<form action="{{ path('my', params) }}" method="GET" class="form-inline">
|
||||||
|
<div class="form-group pull-left">
|
||||||
|
{{ form_widget(filterForm.title) }}
|
||||||
|
</div>
|
||||||
<div class="btn-toolbar">
|
<div class="btn-toolbar">
|
||||||
<div class="btn-group" id="options">
|
<div class="btn-group" id="options">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
@ -202,6 +205,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% set apiEnabled = app.settings.api.enabled %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-{{ apiEnabled ? 6 : 12 }}">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{{ 'login.login.form.password.placeholder'|trans }}
|
{{ 'login.login.form.password.placeholder'|trans }}
|
||||||
|
@ -228,5 +235,32 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if apiEnabled %}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
{{ 'my.api.title'|trans }}
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="tab-content">
|
||||||
|
<p>{{ 'my.api.warning'|trans|raw }}</p>
|
||||||
|
|
||||||
|
<form action="{{ path('my', params) }}" method="post">
|
||||||
|
<div class="row">
|
||||||
|
<p class="col-md-12">
|
||||||
|
<input type="text" name="apiKey" id="form-api-key" class="form-control" value="{{ apiKey }}" data-key="{{ apiKey }}">
|
||||||
|
</p>
|
||||||
|
<p class="col-md-12">
|
||||||
|
<input type="submit" name="generateApiKey" value="{{ 'my.api.form.generate'|trans }}" class="btn btn-primary">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,31 +1,17 @@
|
||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{% if gist.cipher %}
|
|
||||||
<link type="text/css" rel="Stylesheet" href="{{ web_path }}components/SyntaxHighlighter/styles/shCoreRDark.css" />
|
|
||||||
<link type="text/css" rel="Stylesheet" href="{{ web_path }}components/SyntaxHighlighter/styles/shThemeRDark.css" />
|
|
||||||
{% else %}
|
|
||||||
<link rel="stylesheet" href="{{ web_path }}app/css/geshi/vibrant-ink.css" />
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism.css">
|
||||||
|
|
||||||
|
{% if theme_settings.name == 'dark' %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism-okaidia.css">
|
||||||
|
{% else %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism-solarizedlight.css">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
#embed {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#viewer {
|
|
||||||
background: #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 5px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
background: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-body {
|
.panel-body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
@ -34,9 +20,8 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre ol {
|
.container-fluid {
|
||||||
padding-left: 0 !important;
|
padding: 0;
|
||||||
list-style: none;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -46,45 +31,83 @@
|
||||||
{% block nav %}{% endblock %}
|
{% block nav %}{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
{% set routeParams = app.request.attributes.get('_route_params') %}
|
||||||
|
|
||||||
|
{% if type_overrided is defined %}
|
||||||
|
{% set routeParams = routeParams|merge({type: gist.type}) %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12" id="embed">
|
<div class="col-md-12" id="embed">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="pull-right actions">
|
<div class="row">
|
||||||
<a target="_blank" href="{{ path('view', app.request.attributes.get('_route_params')) }}" class="btn btn-default btn-sm cipher-link">
|
<div class="col-md-6 col-xs-9">
|
||||||
|
{{ gist.title ? gist.title : 'gist.untitled'|trans }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-xs-3">
|
||||||
|
<div class="visible-sm visible-xs pull-right">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="glyphicon glyphicon-menu-hamburger"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right">
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="{{ path('view', routeParams) }}" class="cipher-link">
|
||||||
<span class="btn btn-warning btn-xs">
|
<span class="btn btn-warning btn-xs">
|
||||||
{{ commit|slice(0, 10) }}
|
{{ commit|slice(0, 10) }}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
</li>
|
||||||
|
{% if not gist.cipher %}
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="{{ path('raw', routeParams) }}">
|
||||||
|
{{ 'gist.action.raw'|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="{{ path('download', routeParams) }}">
|
||||||
|
{{ 'gist.action.download'|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="{{ path('clone', routeParams) }}" class="cipher-link">
|
||||||
|
{{ 'gist.action.clone'|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="visible-md visible-lg">
|
||||||
|
<div class="text-right actions">
|
||||||
|
<a target="_blank" href="{{ path('view', routeParams) }}" class="cipher-link"><span class="btn btn-warning btn-xs">{{ commit|slice(0, 10) }}</span></a>
|
||||||
|
|
||||||
{% if not gist.cipher %}
|
{% if not gist.cipher %}
|
||||||
<a target="_blank" href="{{ path('raw', app.request.attributes.get('_route_params')) }}" class="btn btn-default btn-sm">
|
<a target="_blank" href="{{ path('raw', routeParams) }}" class="btn btn-default btn-sm">
|
||||||
<span class="glyphicon glyphicon-eye-open"></span>
|
<span class="glyphicon glyphicon-eye-open"></span>
|
||||||
{{ 'gist.action.raw'|trans }}
|
{{ 'gist.action.raw'|trans }}
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="{{ path('download', app.request.attributes.get('_route_params')) }}" class="btn btn-default btn-sm">
|
<a target="_blank" href="{{ path('download', routeParams) }}" class="btn btn-default btn-sm">
|
||||||
<span class="glyphicon glyphicon-save-file"></span>
|
<span class="glyphicon glyphicon-save-file"></span>
|
||||||
{{ 'gist.action.download'|trans }}
|
{{ 'gist.action.download'|trans }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<a target="_blank" href="{{ path('clone', app.request.attributes.get('_route_params')) }}" class="btn btn-success btn-sm cipher-link">
|
<a target="_blank" href="{{ path('clone', routeParams) }}" class="btn btn-success btn-sm cipher-link">
|
||||||
<span class="glyphicon glyphicon-copy"></span>
|
<span class="glyphicon glyphicon-copy"></span>
|
||||||
{{ 'gist.action.clone'|trans }}
|
{{ 'gist.action.clone'|trans }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{{ gist.title ? gist.title : 'gist.untitled'|trans }}
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div id="view" class="tab-pane active in">
|
<div id="view" class="tab-pane active in">
|
||||||
<div id="viewer">
|
<div id="viewer">
|
||||||
{% if gist.cipher %}
|
<pre><code {% if gist.cipher %}data-cipher{% endif %} class="line-numbers language-{{ gist.highlightType }}">{{ raw_content }}</code></pre>
|
||||||
<pre class="brush: {{ gist.type }}; syntaxhighlighter">{{ raw_content|raw }}</pre>
|
|
||||||
{% else %}
|
|
||||||
{{ content|raw }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,37 +123,5 @@
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
<script type="text/javascript" src="{{ web_path }}components/iframe-resizer/js/iframeResizer.contentWindow.min.js"></script>
|
<script type="text/javascript" src="{{ web_path }}components/iframe-resizer/js/iframeResizer.contentWindow.min.js"></script>
|
||||||
|
<script src="{{ web_path }}app/js/prism.js" {% if gist.cipher %}data-manual{% endif %}></script>
|
||||||
{% if gist.cipher %}
|
|
||||||
<script type="text/javascript" src="{{ web_path }}components/SyntaxHighlighter/scripts/XRegExp.js"></script> <!-- XRegExp is bundled with the final shCore.js during build -->
|
|
||||||
<script type="text/javascript" src="{{ web_path }}components/SyntaxHighlighter/scripts/shCore.js"></script>
|
|
||||||
<script type="text/javascript" src="{{ web_path }}components/SyntaxHighlighter/scripts/shAutoloader.js"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
SyntaxHighlighter.autoloader(
|
|
||||||
['applescript', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushAppleScript.js' ],
|
|
||||||
['actionscript3', 'as3', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushAS3.js' ],
|
|
||||||
['bash', 'shell', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushBash.js' ],
|
|
||||||
['coldfusion', 'cf', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushColdFusion.js' ],
|
|
||||||
['cpp', 'c', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushCpp.js' ],
|
|
||||||
['c#', 'c-sharp', 'csharp', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushCSharp.js' ],
|
|
||||||
['css', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushCss.js' ],
|
|
||||||
['delphi', 'pascal', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushDelphi.js' ],
|
|
||||||
['diff', 'patch', 'pas', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushDiff.js' ],
|
|
||||||
['erl', 'erlang', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushErlang.js' ],
|
|
||||||
['groovy', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushGroovy.js' ],
|
|
||||||
['java', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushJava.js' ],
|
|
||||||
['jfx', 'javafx', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushJavaFX.js' ],
|
|
||||||
['js', 'jscript', 'javascript', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushJScript.js' ],
|
|
||||||
['perl', 'pl', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushPerl.js' ],
|
|
||||||
['php', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushPhp.js' ],
|
|
||||||
['text', 'plain', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushPlain.js' ],
|
|
||||||
['py', 'python', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushPython.js' ],
|
|
||||||
['ruby', 'rails', 'ror', 'rb', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushRuby.js' ],
|
|
||||||
['scala', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushScala.js' ],
|
|
||||||
['sql', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushSql.js' ],
|
|
||||||
['vb', 'vbnet', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushVb.js' ],
|
|
||||||
['xml', 'xhtml', 'xslt', 'html', '{{ web_path }}components/SyntaxHighlighter/scripts/shBrushXml.js' ]
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
|
{% set routeParams = app.request.attributes.get('_route_params') %}
|
||||||
|
|
||||||
|
{% if type_overrided is defined %}
|
||||||
|
{% set routeParams = routeParams|merge({type: gist.type}) %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var iFrameResizeLoaded = function() {
|
var iFrameResizeLoaded = function() {
|
||||||
var div = document.getElementById('gist-{{ gist.file }}-{{ commit }}');
|
var div = document.getElementById('gist-{{ gist.file }}-{{ commit }}');
|
||||||
var iframeId = 'gist-' + (Math.floor(Math.random() * (10000 - 1)) + 1).toString();
|
var iframeId = 'gist-' + (Math.floor(Math.random() * (10000 - 1)) + 1).toString();
|
||||||
var iframe = document.createElement('iframe');
|
var iframe = document.createElement('iframe');
|
||||||
var url = '{{ app.request.getSchemeAndHttpHost() ~ path('embed', app.request.attributes.get('_route_params')) }}';
|
var url = '{{ app.request.getSchemeAndHttpHost() ~ path('embed', routeParams) }}';
|
||||||
|
|
||||||
if (div.getAttribute('data-key')) {
|
if (div.getAttribute('data-key')) {
|
||||||
url = [url, div.getAttribute('data-key')].join('');
|
url = [url, div.getAttribute('data-key')].join('');
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<link rel="stylesheet" href="{{ web_path }}app/css/geshi/vibrant-ink.css" />
|
|
||||||
|
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism.css">
|
||||||
|
|
||||||
|
{% if theme_settings.name == 'dark' %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism-okaidia.css">
|
||||||
|
{% else %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism-solarizedlight.css">
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ 'gist.action.history'|trans }}{% endblock %}
|
{% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ 'gist.action.history'|trans }}{% endblock %}
|
||||||
|
@ -52,11 +58,8 @@
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
{% if not loop.first %}
|
{% if not loop.first %}
|
||||||
<div class="diff" id="diff-{{ loop.index }}">
|
<pre><code class="diff language-diff" id="diff-{{ loop.index }}">{% if not gist.cipher %}{{ commit.diff }}{% endif %}</code></pre>
|
||||||
{% if not gist.cipher %}
|
|
||||||
{{ commit.diff|raw }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,10 +79,10 @@
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
{% if gist.cipher %}
|
<script src="{{ web_path }}app/js/prism.js" {% if gist.cipher %}data-manual{% endif %}></script>
|
||||||
{{ include('View/cipherJs.html.twig') }}
|
|
||||||
|
|
||||||
<script src="{{ web_path }}components/jsdiff/diff.min.js"></script>
|
{% if gist.cipher %}
|
||||||
|
<script src="{{ web_path }}components/diff/diff.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var key = getKey();
|
var key = getKey();
|
||||||
|
@ -115,21 +118,19 @@
|
||||||
var lines = value.split("\n");
|
var lines = value.split("\n");
|
||||||
|
|
||||||
for (var i = 0, l = lines.length; i < l; i++) {
|
for (var i = 0, l = lines.length; i < l; i++) {
|
||||||
|
if (lines[i] != '\ No newline at end of file') {
|
||||||
diffContent.push(sign + lines[i]);
|
diffContent.push(sign + lines[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diffContent = diffContent.join("\n");
|
diffContent = diffContent.join("\n");
|
||||||
|
|
||||||
var $pre = $('<pre>')
|
$('#diff-' + (u + 1).toString()).text(diffContent);
|
||||||
.attr('class', 'brush: diff; syntaxhighlighter')
|
|
||||||
.text(diffContent);
|
|
||||||
|
|
||||||
$('#diff-' + (u + 1).toString()).append($pre);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxHighlighter.all();
|
Prism.highlightAll();
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{% if gist.cipher %}
|
|
||||||
<link type="text/css" rel="Stylesheet" href="{{ web_path }}components/SyntaxHighlighter/styles/shCoreRDark.css" />
|
|
||||||
<link type="text/css" rel="Stylesheet" href="{{ web_path }}components/SyntaxHighlighter/styles/shThemeRDark.css" />
|
|
||||||
{% else %}
|
|
||||||
<link rel="stylesheet" href="{{ web_path }}app/css/geshi/vibrant-ink.css" />
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism.css">
|
||||||
|
|
||||||
|
{% if theme_settings.name == 'dark' %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism-okaidia.css">
|
||||||
|
{% else %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/prism-solarizedlight.css">
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ commit|slice(0, 10) }}{% endblock %}
|
{% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ commit|slice(0, 10) }}{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
{% set routeParams = app.request.attributes.get('_route_params') %}
|
||||||
|
|
||||||
|
{% if type_overrided is defined %}
|
||||||
|
{% set routeParams = routeParams|merge({type: gist.type}) %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
|
@ -32,46 +39,116 @@
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="pull-right actions">
|
<div class="row">
|
||||||
|
<div class="col-md-6 col-xs-9">
|
||||||
|
{{ gist.title ? gist.title : 'gist.untitled'|trans }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-xs-3">
|
||||||
|
<div class="visible-sm visible-xs pull-right">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="glyphicon glyphicon-menu-hamburger"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right">
|
||||||
|
<li>
|
||||||
|
<a target="_blank" href="{{ path('view', routeParams) }}" class="cipher-link">
|
||||||
|
<span class="btn btn-warning btn-xs">
|
||||||
|
{{ commit|slice(0, 10) }}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% if not gist.cipher %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('raw', routeParams) }}">
|
||||||
|
{{ 'gist.action.raw'|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('download', routeParams) }}">
|
||||||
|
{{ 'gist.action.download'|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('clone', routeParams) }}" class="cipher-link">
|
||||||
|
{{ 'gist.action.clone'|trans }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="visible-md visible-lg">
|
||||||
|
<div class="text-right actions">
|
||||||
<span class="btn btn-warning btn-xs">
|
<span class="btn btn-warning btn-xs">
|
||||||
{{ commit|slice(0, 10) }}
|
{{ commit|slice(0, 10) }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{% if not gist.cipher %}
|
{% if not gist.cipher %}
|
||||||
<a href="{{ path('raw', app.request.attributes.get('_route_params')) }}" class="btn btn-default btn-sm">
|
<a href="{{ path('raw', routeParams) }}" class="btn btn-default btn-sm">
|
||||||
<span class="glyphicon glyphicon-eye-open"></span>
|
<span class="glyphicon glyphicon-eye-open"></span>
|
||||||
{{ 'gist.action.raw'|trans }}
|
{{ 'gist.action.raw'|trans }}
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ path('download', app.request.attributes.get('_route_params')) }}" class="btn btn-default btn-sm">
|
<a href="{{ path('download', routeParams) }}" class="btn btn-default btn-sm">
|
||||||
<span class="glyphicon glyphicon-save-file"></span>
|
<span class="glyphicon glyphicon-save-file"></span>
|
||||||
{{ 'gist.action.download'|trans }}
|
{{ 'gist.action.download'|trans }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<a href="{{ path('clone', app.request.attributes.get('_route_params')) }}" class="btn btn-success btn-sm cipher-link">
|
<a href="{{ path('clone', routeParams) }}" class="btn btn-success btn-sm cipher-link">
|
||||||
<span class="glyphicon glyphicon-copy"></span>
|
<span class="glyphicon glyphicon-copy"></span>
|
||||||
{{ 'gist.action.clone'|trans }}
|
{{ 'gist.action.clone'|trans }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{{ gist.title ? gist.title : 'gist.untitled'|trans }}
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div id="view" class="tab-pane active in">
|
<div id="view" class="tab-pane active in">
|
||||||
<div id="viewer">
|
<div id="viewer">
|
||||||
{% if gist.cipher %}
|
<pre><code {% if gist.cipher %}data-cipher{% endif %} class="line-numbers language-{{ gist.highlightType }}">{{ raw_content }}</code></pre>
|
||||||
<pre class="brush: {{ gist.type }}; syntaxhighlighter">{{ raw_content|raw }}</pre>
|
|
||||||
{% else %}
|
|
||||||
{{ content|raw }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-toolbar">
|
||||||
|
<div class="pull-right">
|
||||||
|
<div class="btn-group">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||||
|
{{ ('form.type.choice.' ~ gist.type)|trans }}
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right">
|
||||||
|
{% for item in types %}
|
||||||
|
{% if gist.type != item %}
|
||||||
|
<li>
|
||||||
|
{% set params = app.request.attributes.get('_route_params')|merge({type: item}) %}
|
||||||
|
|
||||||
<p id="embed" class="pull-right">
|
<a href="{{ path('view', params) }}">
|
||||||
|
<label for="type-{{ loop.index }}">
|
||||||
|
{{ ('form.type.choice.' ~ item)|trans }}
|
||||||
|
</label>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
{{ 'gist.action.embed'|trans }}
|
{{ 'gist.action.embed'|trans }}
|
||||||
<input type="text" class="form-control" id="embed-input" value="{{ '<div%key%id="gist-' ~ gist.file ~ '-' ~ commit ~ '" class="gist-container"></div><script src="' ~ app.request.getSchemeAndHttpHost() ~ path('embedjs', app.request.attributes.get('_route_params')) ~ '" async></script>' }}" />
|
</div>
|
||||||
</p>
|
<div class="panel-body" id="embed">
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active in">
|
||||||
|
<pre><code class="language-html">{{ '<div%key%id="gist-' ~ gist.file ~ '-' ~ commit ~ '" class="gist-container"></div>
|
||||||
|
<script src="' ~ app.request.getSchemeAndHttpHost() ~ path('embedjs', routeParams) ~ '" async></script>' }}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,7 +160,5 @@
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
{% if gist.cipher %}
|
<script src="{{ web_path }}app/js/prism.js" {% if gist.cipher %}data-manual{% endif %}></script>
|
||||||
{{ include('View/cipherJs.html.twig') }}
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,23 +1,33 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
{% set theme_settings = app.settings.theme %}
|
||||||
|
{% set security_settings = app.settings.security %}
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<link rel="stylesheet" href="{{ web_path }}components/bootstrap/dist/css/bootstrap.min.css" />
|
<link rel="stylesheet" href="{{ web_path }}components/bootstrap/dist/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="{{ web_path }}components/flag-icon-css/css/flag-icon.min.css" />
|
<link rel="stylesheet" href="{{ web_path }}components/flag-icon-css/css/flag-icon.min.css">
|
||||||
<link rel="stylesheet" href="{{ web_path }}app/css/bootstrap/bootstrap.min.css" />
|
|
||||||
<link rel="stylesheet" href="{{ web_path }}app/css/app.css" />
|
{% if theme_settings.name == 'dark' %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/bootstrap/bootstrap.min.css">
|
||||||
|
{% else %}
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}components/bootstrap/dist/css/bootstrap-theme.min.css">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ web_path }}app/css/themes/{{ theme_settings.name }}.css">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block metas %}
|
{% block metas %}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="{{ web_path }}favicon.png">
|
||||||
|
|
||||||
<title>{{ 'app.title_prefix'|trans }}{% block title %}{% endblock %}</title>
|
<title>{{ 'app.title_prefix'|trans }}{% block title %}{% endblock %}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% block nav %}
|
{% block nav %}
|
||||||
<nav class="navbar navbar-inverse">
|
<nav class="navbar navbar-{{ theme_settings.name == 'dark' ? 'inverse' : 'default' }}">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-menu">
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-menu">
|
||||||
|
@ -48,14 +58,14 @@
|
||||||
{{ 'app.menu.my.logout.title'|trans }}
|
{{ 'app.menu.my.logout.title'|trans }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% elseif app.enable_login %}
|
{% elseif security_settings.enable_login %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ path('login') }}">
|
<a href="{{ path('login') }}">
|
||||||
{{ 'app.menu.my.login.title'|trans }}
|
{{ 'app.menu.my.login.title'|trans }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% if app.enable_registration %}
|
{% if security_settings.enable_registration %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ path('register') }}">
|
<a href="{{ path('register') }}">
|
||||||
{{ 'app.menu.my.register.title'|trans }}
|
{{ 'app.menu.my.register.title'|trans }}
|
||||||
|
@ -71,7 +81,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
{% block langs %}
|
{% block langs %}
|
||||||
<p class="navbar-text navbar-right">
|
<p class="navbar-text navbar-right">
|
||||||
{% for locale, flag in {'en': 'gb', 'fr': 'fr', 'es': 'es', 'de': 'de'} %}
|
{% for locale, flag in {'en': 'gb', 'fr': 'fr', 'es': 'es', 'de': 'de', 'cn': 'cn', 'pl': 'pl'} %}
|
||||||
<a class="lang btn btn-xs cipher-link" href="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|merge({_locale: locale})) }}">
|
<a class="lang btn btn-xs cipher-link" href="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|merge({_locale: locale})) }}">
|
||||||
<span class="flag-icon flag-icon-{{ flag }}"></span>
|
<span class="flag-icon flag-icon-{{ flag }}"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -32,25 +32,18 @@ class Gist
|
||||||
*/
|
*/
|
||||||
protected $gitWorkingCopy;
|
protected $gitWorkingCopy;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var GeSHi
|
|
||||||
*/
|
|
||||||
protected $geshi;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __construct.
|
* __construct.
|
||||||
*
|
*
|
||||||
* @param mixed $gistPath
|
* @param mixed $gistPath
|
||||||
* @param GitWrapper $gitWrapper
|
* @param GitWrapper $gitWrapper
|
||||||
* @param GitWorkingCopy $gitWorkingCopy
|
* @param GitWorkingCopy $gitWorkingCopy
|
||||||
* @param GeSHi $geshi
|
|
||||||
*/
|
*/
|
||||||
public function __construct($gistPath, GitWrapper $gitWrapper, GitWorkingCopy $gitWorkingCopy, GeSHi $geshi)
|
public function __construct($gistPath, GitWrapper $gitWrapper, GitWorkingCopy $gitWorkingCopy)
|
||||||
{
|
{
|
||||||
$this->gistPath = $gistPath;
|
$this->gistPath = $gistPath;
|
||||||
$this->gitWrapper = $gitWrapper;
|
$this->gitWrapper = $gitWrapper;
|
||||||
$this->gitWorkingCopy = $gitWorkingCopy;
|
$this->gitWorkingCopy = $gitWorkingCopy;
|
||||||
$this->geshi = $geshi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,7 +88,7 @@ class Gist
|
||||||
$data = array(
|
$data = array(
|
||||||
'commit' => trim($commits[$i][1]),
|
'commit' => trim($commits[$i][1]),
|
||||||
'date' => new \DateTime(trim($dates[$i][1])),
|
'date' => new \DateTime(trim($dates[$i][1])),
|
||||||
'diff' => $this->highlight('diff', $diff),
|
'diff' => str_replace('\ No newline at end of file', '', $diff),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($gist->isCipher()) {
|
if ($gist->isCipher()) {
|
||||||
|
@ -149,7 +142,7 @@ class Gist
|
||||||
$gist->setUser($user);
|
$gist->setUser($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
$gist->save();
|
$gist->commit()->save();
|
||||||
|
|
||||||
return $gist;
|
return $gist;
|
||||||
}
|
}
|
||||||
|
@ -170,22 +163,27 @@ class Gist
|
||||||
->add($gist->getFile())
|
->add($gist->getFile())
|
||||||
->commit('Update');
|
->commit('Update');
|
||||||
|
|
||||||
|
$gist->commit()->save();
|
||||||
|
|
||||||
return $gist;
|
return $gist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Highlight the content.
|
* Returns the number of commits.
|
||||||
*
|
*
|
||||||
* @param string $type
|
* @param GistModel $gist
|
||||||
* @param string $content
|
|
||||||
*
|
*
|
||||||
* @return string
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function highlight($type, $content)
|
public function getNumberOfCommits(GistModel $gist)
|
||||||
{
|
{
|
||||||
$this->geshi->set_source($content);
|
$command = GitCommand::getInstance('log', '--oneline', '--', $gist->getFile());
|
||||||
$this->geshi->set_language($type);
|
$command->setDirectory($this->gistPath);
|
||||||
|
$command->bypass(false);
|
||||||
|
|
||||||
return $this->geshi->parse_code();
|
$content = trim($this->gitWrapper->run($command));
|
||||||
|
$content = str_replace("\r\n", "\n", $content);
|
||||||
|
|
||||||
|
return count(explode("\n", $content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,30 @@ class SaltGenerator
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function generate($length = 32)
|
public function generate($length = 32, $isApiKey = false)
|
||||||
{
|
{
|
||||||
if (!is_numeric($length)) {
|
if (!is_numeric($length)) {
|
||||||
throw new InvalidArgumentException('Paramter length must be a valid integer.');
|
throw new InvalidArgumentException('Paramter length must be a valid integer.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||||
return substr(base64_encode(openssl_random_pseudo_bytes($length)), 0, $length);
|
$string = base64_encode(openssl_random_pseudo_bytes(256));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('mcrypt_create_iv')) {
|
if (function_exists('mcrypt_create_iv')) {
|
||||||
return substr(base64_encode(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)), 0, $length);
|
$string = base64_encode(mcrypt_create_iv(256, MCRYPT_DEV_URANDOM));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($string)) {
|
||||||
|
if (true === $isApiKey) {
|
||||||
|
$string = str_replace(
|
||||||
|
array('+', '%', '/', '#', '&'),
|
||||||
|
'',
|
||||||
|
$string
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($string, 0, $length);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException('You must enable openssl or mcrypt modules.');
|
throw new RuntimeException('You must enable openssl or mcrypt modules.');
|
||||||
|
|
|
@ -126,6 +126,7 @@ class UserProvider implements UserProviderInterface
|
||||||
$user
|
$user
|
||||||
->setRoles('ROLE_USER')
|
->setRoles('ROLE_USER')
|
||||||
->setPassword($this->encoder->encodePassword($password, $user->getSalt()))
|
->setPassword($this->encoder->encodePassword($password, $user->getSalt()))
|
||||||
|
->setApiKey($this->saltGenerator->generate(32, true))
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
|
@ -166,6 +167,20 @@ class UserProvider implements UserProviderInterface
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a user by his api key.
|
||||||
|
*
|
||||||
|
* @param string $apiKey
|
||||||
|
*
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
public function loadUserByApiKey($apiKey)
|
||||||
|
{
|
||||||
|
$user = UserQuery::create()->findOneByApiKey($apiKey);
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if the given password is the current user password.
|
* Checks if the given password is the current user password.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
/* @override http://localhost/mark_story2/site/css/geshi.css */
|
|
||||||
/**
|
|
||||||
* GeSHi CSS Inspired by
|
|
||||||
* TextMate Theme Dawn
|
|
||||||
*
|
|
||||||
* Copyright 2008 Mark Story
|
|
||||||
*
|
|
||||||
* This work is licensed under the Creative Commons Attribution-Share Alike 2.5 Canada License.
|
|
||||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
|
||||||
*
|
|
||||||
* @copyright Copyright 2008, Mark Story.
|
|
||||||
* @link http://mark-story.com
|
|
||||||
* @license http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Global geshi styles
|
|
||||||
**********************/
|
|
||||||
#main pre {
|
|
||||||
line-height: 1.5em;
|
|
||||||
font-size: 10px;
|
|
||||||
white-space: normal;
|
|
||||||
padding: 0;
|
|
||||||
background: #E8EDF4;
|
|
||||||
border: 1px solid #222;
|
|
||||||
}
|
|
||||||
pre ol {
|
|
||||||
list-style: decimal;
|
|
||||||
list-style-position: outside;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#main pre ol li {
|
|
||||||
margin: 0 0 0 35px;
|
|
||||||
padding: 0;
|
|
||||||
color: #333;
|
|
||||||
clear: none;
|
|
||||||
}
|
|
||||||
pre ol li div {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Line highlights */
|
|
||||||
.li1 {
|
|
||||||
background: #E4E8EF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* comments */
|
|
||||||
.co1,
|
|
||||||
.coMULTI {
|
|
||||||
color:#5A526E;
|
|
||||||
}
|
|
||||||
/* methods */
|
|
||||||
.me1{
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
.me0 {
|
|
||||||
|
|
||||||
}
|
|
||||||
.me2 {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* brackets */
|
|
||||||
.br0 {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strings */
|
|
||||||
.st0 {
|
|
||||||
color:#0B6125;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keywords */
|
|
||||||
.kw1 {
|
|
||||||
color: #794938;
|
|
||||||
}
|
|
||||||
.kw2 {
|
|
||||||
color:#A71D5D;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kw3 {
|
|
||||||
color:#693A17;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* numbers */
|
|
||||||
.nu0 {
|
|
||||||
color:#811F24;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vars */
|
|
||||||
.re0 {
|
|
||||||
color:#434A97;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CSS selectors
|
|
||||||
*****************/
|
|
||||||
/* classnames */
|
|
||||||
|
|
||||||
[lang=css] .kw2,
|
|
||||||
.css .kw2 {
|
|
||||||
color:#C24F24;
|
|
||||||
}
|
|
||||||
[lang=css] .kw1,
|
|
||||||
.css .kw1 {
|
|
||||||
color:#691C97;
|
|
||||||
}
|
|
||||||
[lang=css] .re0,
|
|
||||||
.css .re0 {
|
|
||||||
color: #C24F24;
|
|
||||||
}
|
|
||||||
.re1 {
|
|
||||||
color: #C24F24;
|
|
||||||
}
|
|
||||||
/* px values */
|
|
||||||
[lang=css] .re3,
|
|
||||||
.css .re3 {
|
|
||||||
color:#84252A;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Python
|
|
||||||
****************/
|
|
||||||
[lang=python] ol li div,
|
|
||||||
.python ol li div {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
[lang=python] .kw2,
|
|
||||||
.python .kw2 {
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
[lang=python] .kw1 {
|
|
||||||
color: #A91D5D;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Javascript
|
|
||||||
****************/
|
|
||||||
[lang=javascript] .me1,
|
|
||||||
.javascript .me1 {
|
|
||||||
color: #794938;
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
/**
|
|
||||||
* GeSHi CSS Inspired by TextMate
|
|
||||||
* Theme Mac Classic
|
|
||||||
*
|
|
||||||
* Copyright 2008 Mark Story
|
|
||||||
*
|
|
||||||
* This work is licensed under the Creative Commons Attribution-Share Alike 2.5 Canada License.
|
|
||||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
|
||||||
*
|
|
||||||
* @copyright Copyright 2008, Mark Story.
|
|
||||||
* @link http://mark-story.com
|
|
||||||
* @license http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Global geshi styles
|
|
||||||
**********************/
|
|
||||||
#main pre {
|
|
||||||
line-height: 1.5em;
|
|
||||||
font-size: 10px;
|
|
||||||
white-space: normal;
|
|
||||||
padding: 0;
|
|
||||||
background: #eae9e5;
|
|
||||||
border: 1px solid #c0c0c0;
|
|
||||||
}
|
|
||||||
pre ol {
|
|
||||||
list-style: decimal;
|
|
||||||
list-style-position: outside;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#main pre ol li {
|
|
||||||
margin: 0 0 0 35px;
|
|
||||||
padding: 0;
|
|
||||||
color: #000;
|
|
||||||
clear: none;
|
|
||||||
}
|
|
||||||
pre ol li div {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* php */
|
|
||||||
pre[lang=php] ol div,
|
|
||||||
pre.php ol div {
|
|
||||||
color:#fd1435;
|
|
||||||
}
|
|
||||||
/* Line highlights */
|
|
||||||
.li1 {
|
|
||||||
background: #f2f2f2;
|
|
||||||
}
|
|
||||||
/* Line highlights */
|
|
||||||
.li1 {
|
|
||||||
background: #f2f2f2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* comments */
|
|
||||||
.co1,
|
|
||||||
.coMULTI {
|
|
||||||
color:#5c9dff;
|
|
||||||
}
|
|
||||||
/* methods */
|
|
||||||
.me1{
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
.me0 {
|
|
||||||
|
|
||||||
}
|
|
||||||
.me2 {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* brackets */
|
|
||||||
.br0 {
|
|
||||||
color:#222;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strings */
|
|
||||||
.st0 {
|
|
||||||
color:#b701bb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keywords */
|
|
||||||
.kw1 {
|
|
||||||
color: #fd1435;
|
|
||||||
}
|
|
||||||
.kw2 {
|
|
||||||
color:#6266f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kw3 {
|
|
||||||
color:#505e80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* numbers */
|
|
||||||
.nu0 {
|
|
||||||
color:#0a0aa5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vars */
|
|
||||||
.re0 {
|
|
||||||
color:#059532;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CSS selectors
|
|
||||||
*****************/
|
|
||||||
/* classnames */
|
|
||||||
|
|
||||||
[lang=css] .kw2,
|
|
||||||
.css .kw2 {
|
|
||||||
color:#0a0aa5;
|
|
||||||
}
|
|
||||||
.re1 {
|
|
||||||
color: #b701bb;
|
|
||||||
}
|
|
||||||
/* px values */
|
|
||||||
[lang=css] .re3,
|
|
||||||
.css .re3 {
|
|
||||||
color:#059532;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Javascript
|
|
||||||
****************/
|
|
||||||
[lang=javascript] .me1,
|
|
||||||
.javascript .me1 {
|
|
||||||
color:#505e80;
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
/* @override http://localhost/mark_story2/site/css/geshi.css */
|
|
||||||
/**
|
|
||||||
* GeSHi CSS Inspired by TextMate
|
|
||||||
* Theme Twilight
|
|
||||||
*
|
|
||||||
* Copyright 2008 Mark Story
|
|
||||||
*
|
|
||||||
* This work is licensed under the Creative Commons Attribution-Share Alike 2.5 Canada License.
|
|
||||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
|
||||||
*
|
|
||||||
* @filesource
|
|
||||||
* @copyright Copyright 2008, Mark Story.
|
|
||||||
* @link http://mark-story.com
|
|
||||||
* @license http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Global geshi styles
|
|
||||||
**********************/
|
|
||||||
#main pre {
|
|
||||||
line-height: 1.5em;
|
|
||||||
font-size: 10px;
|
|
||||||
white-space: normal;
|
|
||||||
padding: 0;
|
|
||||||
background: #222223;
|
|
||||||
border: 1px solid #222;
|
|
||||||
}
|
|
||||||
pre ol {
|
|
||||||
list-style: decimal;
|
|
||||||
list-style-position: outside;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#main pre ol li {
|
|
||||||
margin: 0 0 0 35px;
|
|
||||||
padding: 0;
|
|
||||||
color: #000;
|
|
||||||
clear: none;
|
|
||||||
}
|
|
||||||
pre ol li div {
|
|
||||||
color:#f8f8f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Line highlights */
|
|
||||||
.li1 {
|
|
||||||
background: #202021;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* comments */
|
|
||||||
.co1,
|
|
||||||
.coMULTI {
|
|
||||||
color:#5F5A60;
|
|
||||||
}
|
|
||||||
/* methods */
|
|
||||||
.me1{
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
.me0 {
|
|
||||||
|
|
||||||
}
|
|
||||||
.me2 {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* brackets */
|
|
||||||
.br0 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strings */
|
|
||||||
.st0 {
|
|
||||||
color:#8F9657;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keywords */
|
|
||||||
.kw1 {
|
|
||||||
color: #CDA869;
|
|
||||||
}
|
|
||||||
.kw2 {
|
|
||||||
color:#F9EE98;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kw3 {
|
|
||||||
color:#505e80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* numbers */
|
|
||||||
.nu0 {
|
|
||||||
color:#CF6745;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vars */
|
|
||||||
.re0 {
|
|
||||||
color:#7587A6;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CSS selectors
|
|
||||||
*****************/
|
|
||||||
/* classnames */
|
|
||||||
|
|
||||||
[lang=css] .kw2,
|
|
||||||
.css .kw2 {
|
|
||||||
color:#F9EE7E;
|
|
||||||
}
|
|
||||||
.re1 {
|
|
||||||
color: #96703D;
|
|
||||||
}
|
|
||||||
/* px values */
|
|
||||||
[lang=css] .re3,
|
|
||||||
.css .re3 {
|
|
||||||
color:#CA7840;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Javascript
|
|
||||||
****************/
|
|
||||||
[lang=javascript] .me1,
|
|
||||||
.javascript .me1 {
|
|
||||||
color:#505e80;
|
|
||||||
}
|
|
|
@ -1,148 +0,0 @@
|
||||||
/* @override http://localhost/mark_story2/site/css/geshi.css */
|
|
||||||
/**
|
|
||||||
* GeSHi CSS Inspired by TextMate
|
|
||||||
* Theme Vibrant Ink
|
|
||||||
*
|
|
||||||
* Copyright 2008 Mark Story
|
|
||||||
*
|
|
||||||
* This work is licensed under the Creative Commons Attribution-Share Alike 2.5 Canada License.
|
|
||||||
* To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
|
|
||||||
*
|
|
||||||
* @copyright Copyright 2008, Mark Story.
|
|
||||||
* @link http://mark-story.com
|
|
||||||
* @license http://creativecommons.org/licenses/by-sa/2.5/ca/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Global geshi styles
|
|
||||||
**********************/
|
|
||||||
#main pre {
|
|
||||||
line-height: 1.5em;
|
|
||||||
font-size: 10px;
|
|
||||||
white-space: normal;
|
|
||||||
padding: 0;
|
|
||||||
background: #000;
|
|
||||||
border: 1px solid #222;
|
|
||||||
}
|
|
||||||
pre ol {
|
|
||||||
list-style: decimal;
|
|
||||||
list-style-position: outside;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#main pre ol li {
|
|
||||||
margin: 0 0 0 35px;
|
|
||||||
padding: 0;
|
|
||||||
color: #fff;
|
|
||||||
clear: none;
|
|
||||||
}
|
|
||||||
pre ol li div {
|
|
||||||
/*color: #F26100;*/
|
|
||||||
color: #D2C0B4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Line highlights */
|
|
||||||
.li1 {
|
|
||||||
background: #030303;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* comments */
|
|
||||||
.co1,
|
|
||||||
.coMULTI {
|
|
||||||
color:#7830CC;
|
|
||||||
}
|
|
||||||
/* methods */
|
|
||||||
.me1{
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
.me0 {
|
|
||||||
|
|
||||||
}
|
|
||||||
.me2 {
|
|
||||||
color:#000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* brackets */
|
|
||||||
.br0 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strings */
|
|
||||||
.st0 {
|
|
||||||
color:#52F700;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keywords */
|
|
||||||
.kw1 {
|
|
||||||
color: #C6C765;
|
|
||||||
}
|
|
||||||
.kw2 {
|
|
||||||
color:#FFC500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kw3 {
|
|
||||||
color:#505e80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* numbers */
|
|
||||||
.nu0 {
|
|
||||||
color:#319994;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vars */
|
|
||||||
.re0 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CSS selectors
|
|
||||||
*****************/
|
|
||||||
/* classnames */
|
|
||||||
|
|
||||||
[lang=css] .kw2,
|
|
||||||
.css .kw2 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
[lang=css] .kw1,
|
|
||||||
.css .kw1 {
|
|
||||||
color:#999966;
|
|
||||||
}
|
|
||||||
[lang=css] .re0,
|
|
||||||
.css .re0 {
|
|
||||||
color: #F26100;
|
|
||||||
}
|
|
||||||
.re1 {
|
|
||||||
color: #96703D;
|
|
||||||
}
|
|
||||||
/* px values */
|
|
||||||
[lang=css] .re3,
|
|
||||||
.css .re3 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Python
|
|
||||||
****************/
|
|
||||||
[lang=python] ol li div,
|
|
||||||
.python ol li div {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
[lang=python] .kw1,
|
|
||||||
.python .kw1 {
|
|
||||||
color:#F26100;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Javascript
|
|
||||||
****************/
|
|
||||||
[lang=javascript] .me1,
|
|
||||||
.javascript .me1 {
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
pre[lang=javascript] ol li div,
|
|
||||||
.javascript ol li div {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
121
web/app/css/prism-okaidia.css
Normal file
121
web/app/css/prism-okaidia.css
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
/**
|
||||||
|
* okaidia theme for JavaScript, CSS and HTML
|
||||||
|
* Loosely based on Monokai textmate theme by http://www.monokai.nl/
|
||||||
|
* @author ocodia
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: #f8f8f2;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
border-radius: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #272822;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #f8f8f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #f92672;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.boolean,
|
||||||
|
.token.number {
|
||||||
|
color: #ae81ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #a6e22e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string,
|
||||||
|
.token.variable {
|
||||||
|
color: #f8f8f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.function {
|
||||||
|
color: #e6db74;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.keyword {
|
||||||
|
color: #66d9ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important {
|
||||||
|
color: #fd971f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
148
web/app/css/prism-solarizedlight.css
Normal file
148
web/app/css/prism-solarizedlight.css
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
Solarized Color Schemes originally by Ethan Schoonover
|
||||||
|
http://ethanschoonover.com/solarized
|
||||||
|
|
||||||
|
Ported for PrismJS by Hector Matos
|
||||||
|
Website: https://krakendev.io
|
||||||
|
Twitter Handle: https://twitter.com/allonsykraken)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
SOLARIZED HEX
|
||||||
|
--------- -------
|
||||||
|
base03 #002b36
|
||||||
|
base02 #073642
|
||||||
|
base01 #586e75
|
||||||
|
base00 #657b83
|
||||||
|
base0 #839496
|
||||||
|
base1 #93a1a1
|
||||||
|
base2 #eee8d5
|
||||||
|
base3 #fdf6e3
|
||||||
|
yellow #b58900
|
||||||
|
orange #cb4b16
|
||||||
|
red #dc322f
|
||||||
|
magenta #d33682
|
||||||
|
violet #6c71c4
|
||||||
|
blue #268bd2
|
||||||
|
cyan #2aa198
|
||||||
|
green #859900
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: #657b83; /* base00 */
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
background: #073642; /* base02 */
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
background: #073642; /* base02 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
border-radius: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background-color: #fdf6e3; /* base3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: #93a1a1; /* base1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #586e75; /* base01 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #268bd2; /* blue */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.url,
|
||||||
|
.token.inserted {
|
||||||
|
color: #2aa198; /* cyan */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
color: #657b83; /* base00 */
|
||||||
|
background: #eee8d5; /* base2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #859900; /* green */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function {
|
||||||
|
color: #b58900; /* yellow */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #cb4b16; /* orange */
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
233
web/app/css/prism.css
Normal file
233
web/app/css/prism.css
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/* PrismJS 1.15.0
|
||||||
|
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+actionscript+c+csharp+bash+cpp+aspnet+css-extras+diff+markup-templating+markdown+perl+php+php-extras+sql+python+yaml&plugins=line-highlight+line-numbers */
|
||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #9a6e3a;
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function,
|
||||||
|
.token.class-name {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[data-line] {
|
||||||
|
position: relative;
|
||||||
|
padding: 1em 0 1em 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-highlight {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: inherit 0;
|
||||||
|
margin-top: 1em; /* Same as .prism’s padding-top */
|
||||||
|
|
||||||
|
background: hsla(24, 20%, 50%,.08);
|
||||||
|
background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
line-height: inherit;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-highlight:before,
|
||||||
|
.line-highlight[data-end]:after {
|
||||||
|
content: attr(data-start);
|
||||||
|
position: absolute;
|
||||||
|
top: .4em;
|
||||||
|
left: .6em;
|
||||||
|
min-width: 1em;
|
||||||
|
padding: 0 .5em;
|
||||||
|
background-color: hsla(24, 20%, 50%,.4);
|
||||||
|
color: hsl(24, 20%, 95%);
|
||||||
|
font: bold 65%/1.5 sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: .3em;
|
||||||
|
border-radius: 999px;
|
||||||
|
text-shadow: none;
|
||||||
|
box-shadow: 0 1px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-highlight[data-end]:after {
|
||||||
|
content: attr(data-end);
|
||||||
|
top: auto;
|
||||||
|
bottom: .4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers .line-highlight:before,
|
||||||
|
.line-numbers .line-highlight:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"].line-numbers {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 3.8em;
|
||||||
|
counter-reset: linenumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"].line-numbers > code {
|
||||||
|
position: relative;
|
||||||
|
white-space: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers .line-numbers-rows {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
top: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
left: -3.8em;
|
||||||
|
width: 3em; /* works for line-numbers below 1000 lines */
|
||||||
|
letter-spacing: -1px;
|
||||||
|
border-right: 1px solid #999;
|
||||||
|
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-rows > span {
|
||||||
|
pointer-events: none;
|
||||||
|
display: block;
|
||||||
|
counter-increment: linenumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-rows > span:before {
|
||||||
|
content: counter(linenumber);
|
||||||
|
color: #999;
|
||||||
|
display: block;
|
||||||
|
padding-right: 0.8em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
|
@ -26,54 +26,24 @@ body {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
#viewer pre, #viewer code, #revisions pre, #revisions code, #embed pre, #embed code {
|
||||||
background: #222;
|
background: none !important;
|
||||||
border: #222;
|
|
||||||
color: #ddd;
|
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
white-space: -moz-pre-wrap;
|
white-space: -moz-pre-wrap;
|
||||||
white-space: -pre-wrap;
|
white-space: -pre-wrap;
|
||||||
white-space: -o-pre-wrap;
|
white-space: -o-pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
border: 0;
|
||||||
|
|
||||||
pre ol {
|
|
||||||
padding-left: 50px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre li:hover {
|
|
||||||
background: #444;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-heading .actions {
|
.panel-heading .actions {
|
||||||
margin-top: -5px;
|
margin-top: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.diff {
|
.diff {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.de1 {
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.li1 {
|
|
||||||
background: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.re8 {
|
|
||||||
color: #52F700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kw3 {
|
|
||||||
color: #C6C765;
|
|
||||||
}
|
|
||||||
|
|
||||||
#viewer .syntaxhighlighter td {
|
|
||||||
vertical-align: top !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#options {
|
#options {
|
||||||
margin-bottom: 17px;
|
margin-bottom: 17px;
|
||||||
}
|
}
|
||||||
|
@ -86,3 +56,11 @@ div.diff {
|
||||||
.btn-error:active, .btn-error:hover, .btn-error:focus {
|
.btn-error:active, .btn-error:hover, .btn-error:focus {
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre.line-numbers {
|
||||||
|
padding-left: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-rows {
|
||||||
|
top: -4px !important;
|
||||||
|
}
|
56
web/app/css/themes/light.css
Normal file
56
web/app/css/themes/light.css
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
.navbar {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form_content {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#languages {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#languages .btn-group:first-child {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, code {
|
||||||
|
background: none !important;
|
||||||
|
white-space: pre-wrap !important;
|
||||||
|
white-space: -moz-pre-wrap !important;
|
||||||
|
white-space: -pre-wrap !important;
|
||||||
|
white-space: -o-pre-wrap !important;
|
||||||
|
word-wrap: break-word !important;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading .actions {
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#options {
|
||||||
|
margin-bottom: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-delete {
|
||||||
|
background: #DE3336;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-error:active, .btn-error:hover, .btn-error:focus {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.line-numbers {
|
||||||
|
padding-left: 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-rows {
|
||||||
|
top: -4px !important;
|
||||||
|
}
|
|
@ -98,6 +98,10 @@ var myEvents = function() {
|
||||||
$('#form-deletion form').submit();
|
$('#form-deletion form').submit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('change keyup keydown', '#form-api-key', function() {
|
||||||
|
$(this).val($(this).data('key'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var mainEditorEvents = function() {
|
var mainEditorEvents = function() {
|
||||||
|
@ -134,13 +138,13 @@ var getKey = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewerEvents = function() {
|
var viewerEvents = function() {
|
||||||
var $render = $('.syntaxhighlighter');
|
var $render = $('#viewer code[data-cipher]');
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var key = getKey();
|
var key = getKey();
|
||||||
|
|
||||||
var $cipherEditor = $('.cipher-editor');
|
var $cipherEditor = $('.cipher-editor');
|
||||||
var $embedInput = $('#embed-input');
|
var $embedCode = $('#embed code');
|
||||||
|
|
||||||
var to = ' ';
|
var to = ' ';
|
||||||
|
|
||||||
|
@ -159,7 +163,8 @@ var viewerEvents = function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$render.text(decrypted.toString(CryptoJS.enc.Utf8));
|
$render.text(decrypted.toString(CryptoJS.enc.Utf8));
|
||||||
SyntaxHighlighter.all();
|
$render.attr('class', $render.data('class'));
|
||||||
|
Prism.highlightAll();
|
||||||
|
|
||||||
to = ' data-key="#key=' + key + '" ';
|
to = ' data-key="#key=' + key + '" ';
|
||||||
} else {
|
} else {
|
||||||
|
@ -172,8 +177,9 @@ var viewerEvents = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($embedInput.length) {
|
if ($embedCode.length) {
|
||||||
$embedInput.val($embedInput.val().replace('%key%', to));
|
$embedCode.html($embedCode.html().replace('%key%', to));
|
||||||
|
Prism.highlightAll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
25
web/app/js/prism.js
Normal file
25
web/app/js/prism.js
Normal file
File diff suppressed because one or more lines are too long
1
web/components/bootstrap
Symbolic link
1
web/components/bootstrap
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/bootstrap
|
1
web/components/diff
Symbolic link
1
web/components/diff
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/diff
|
1
web/components/flag-icon-css
Symbolic link
1
web/components/flag-icon-css
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/flag-icon-css
|
1
web/components/iframe-resizer
Symbolic link
1
web/components/iframe-resizer
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/iframe-resizer
|
1
web/components/jquery
Symbolic link
1
web/components/jquery
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../node_modules/jquery
|
BIN
web/favicon.png
Normal file
BIN
web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 570 B |
|
@ -4,4 +4,4 @@ $app = require __DIR__.'/../app/bootstrap.php';
|
||||||
|
|
||||||
$app['env'] = 'prod';
|
$app['env'] = 'prod';
|
||||||
|
|
||||||
$app->run();
|
$app['http_cache']->run();
|
||||||
|
|
Loading…
Reference in a new issue