From 1c52988222c991ca3ab4e909c1908a39d88c302a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 24 Apr 2017 20:56:53 +0200 Subject: [PATCH 01/79] Fix issue for data path conf --- app/bootstrap.php.d/50-git.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bootstrap.php.d/50-git.php b/app/bootstrap.php.d/50-git.php index 9511253..728e2c9 100644 --- a/app/bootstrap.php.d/50-git.php +++ b/app/bootstrap.php.d/50-git.php @@ -6,7 +6,7 @@ use Gist\Service\Gist; $dataPath = $app['settings']['data']['path']; if ($dataPath[0] !== '/') { - $app['gist_path'] = $app['root_path'].$dataPath; + $app['gist_path'] = $app['root_path'].'/'.$dataPath; } else { $app['gist_path'] = $dataPath; } From 0060b188427851efcf2f09c2685c9c7b46755860 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 4 Jun 2017 17:27:01 +0200 Subject: [PATCH 02/79] API base url setting --- app/bootstrap.php.d/60-api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bootstrap.php.d/60-api.php b/app/bootstrap.php.d/60-api.php index c66683b..4892f39 100644 --- a/app/bootstrap.php.d/60-api.php +++ b/app/bootstrap.php.d/60-api.php @@ -3,5 +3,5 @@ use Gist\Api\Client; $app['api_client'] = $app->share(function ($app) { - return new Client(['base_uri' => $app['settings']['api']['base_uri']]); + return new Client(['base_uri' => rtrim($app['settings']['api']['base_url'], '/')]); }); From 1898c31e21f247cd47ba70ffbca06080cc60a515 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 4 Jun 2017 17:30:46 +0200 Subject: [PATCH 03/79] Chinese translations --- app/bootstrap.php.d/30-trans.php | 2 +- src/Gist/Resources/views/base.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/bootstrap.php.d/30-trans.php b/app/bootstrap.php.d/30-trans.php index 527de85..e18aff5 100644 --- a/app/bootstrap.php.d/30-trans.php +++ b/app/bootstrap.php.d/30-trans.php @@ -11,7 +11,7 @@ use Symfony\Component\HttpFoundation\Cookie; $app->register(new TranslationServiceProvider(), array( 'locale' => 'en', 'locale_fallback' => 'en', - 'locales' => array('en', 'fr', 'es', 'de'), + 'locales' => array('en', 'fr', 'es', 'de', 'cn'), )); $app['translator'] = $app->extend('translator', function ($translator, $app) { diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index 2410dd7..046d5f1 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -79,7 +79,7 @@ {% block langs %}
-
+
@@ -71,6 +71,10 @@ {{ form_errors(form.content) }} {{ form_widget(form.content) }}

+

+ {{ form_errors(form.file) }} + {{ form_widget(form.file) }} +

diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index 046d5f1..d9d83e2 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -106,6 +106,7 @@ var trans = function(key) { var translations = { 'form.confirm': '{{ 'form.confirm'|trans }}', + 'form.error.not_blank': '{{ 'form.confirm'|trans }}', }; if (translations.hasOwnProperty(key)) { From bc67a2ce1c5f4c9507fdc3c237435ae6d8f64ba7 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 19 Jun 2017 23:55:50 +0200 Subject: [PATCH 06/79] Fix form validation --- src/Gist/Controller/EditController.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Gist/Controller/EditController.php b/src/Gist/Controller/EditController.php index 348e989..8c188ef 100644 --- a/src/Gist/Controller/EditController.php +++ b/src/Gist/Controller/EditController.php @@ -8,6 +8,7 @@ use Gist\Form\CloneGistForm; use Gist\Model\Gist; use GitWrapper\GitException; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Form\FormError; /** * Class EditController. @@ -37,9 +38,19 @@ class EditController extends Controller if ($request->isMethod('post')) { $form->submit($request); + $data = $form->getData(); + + if (empty($form->getData()['content']) && !$request->files->has('file')) { + $form->get('content')->addError(new FormError($app['translator']->trans('form.error.not_blank'))); + } elseif (empty($form->getData()['content']) && $request->files->has('file')) { + if (count($form->get('file')->getErrors()) === 0) { + $data['content'] = file_get_contents($form->get('file')->getData()->getPathName()); + unset($data['file']); + } + } if ($form->isValid()) { - $gist = $app['gist']->create(new Gist(), $form->getData(), $this->getUser()); + $gist = $app['gist']->create(new Gist(), $data, $this->getUser()); } } From 79ba41a9839e1b5eee8d7108658f9899d32cc6fd Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 20 Jun 2017 09:47:51 +0200 Subject: [PATCH 07/79] Apply hotfix --- src/Gist/Resources/views/base.html.twig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index d9d83e2..046d5f1 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -106,7 +106,6 @@ var trans = function(key) { var translations = { 'form.confirm': '{{ 'form.confirm'|trans }}', - 'form.error.not_blank': '{{ 'form.confirm'|trans }}', }; if (translations.hasOwnProperty(key)) { From c46cf0fdb72ebf5c02e786e35a78a477362728dc Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 20 Jun 2017 10:03:40 +0200 Subject: [PATCH 08/79] Fix form validation --- src/Gist/Controller/EditController.php | 10 ++++------ src/Gist/Resources/views/base.html.twig | 6 +++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Gist/Controller/EditController.php b/src/Gist/Controller/EditController.php index 8c188ef..d9a4ceb 100644 --- a/src/Gist/Controller/EditController.php +++ b/src/Gist/Controller/EditController.php @@ -40,13 +40,11 @@ class EditController extends Controller $form->submit($request); $data = $form->getData(); - if (empty($form->getData()['content']) && !$request->files->has('file')) { + if (empty($form->getData()['content']) && $form->get('file')->getData()) { + $data['content'] = file_get_contents($form->get('file')->getData()->getPathName()); + unset($data['file']); + } elseif (empty($form->getData()['content'])) { $form->get('content')->addError(new FormError($app['translator']->trans('form.error.not_blank'))); - } elseif (empty($form->getData()['content']) && $request->files->has('file')) { - if (count($form->get('file')->getErrors()) === 0) { - $data['content'] = file_get_contents($form->get('file')->getData()->getPathName()); - unset($data['file']); - } } if ($form->isValid()) { diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index 046d5f1..9146d00 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -1,6 +1,6 @@ {% set theme_settings = app.settings.theme %} -{% set security_dettings = app.settings.security %} +{% set security_settings = app.settings.security %} {% block css %} @@ -56,14 +56,14 @@ {{ 'app.menu.my.logout.title'|trans }} - {% elseif security_dettings.enable_login %} + {% elseif security_settings.enable_login %}
  • {{ 'app.menu.my.login.title'|trans }}
  • - {% if security_dettings.enable_registration %} + {% if security_settings.enable_registration %}
  • {{ 'app.menu.my.register.title'|trans }} From 50025705d1c2fb49254535032b01637029d0038f Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 20 Jun 2017 16:46:10 +0200 Subject: [PATCH 09/79] Fix login issue --- src/Gist/Controller/LoginController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Gist/Controller/LoginController.php b/src/Gist/Controller/LoginController.php index a45d1a3..f835306 100644 --- a/src/Gist/Controller/LoginController.php +++ b/src/Gist/Controller/LoginController.php @@ -26,7 +26,7 @@ class LoginController extends Controller { $app = $this->getApp(); - if (false === $app['settings']['enable_registration']) { + if (false === $app['settings']['security']['enable_registration']) { return new Response('', 403); } @@ -78,7 +78,7 @@ class LoginController extends Controller { $app = $this->getApp(); - if (false === $app['settings']['enable_login']) { + if (false === $app['settings']['security']['enable_login']) { return new Response('', 403); } From a9435906fe813abaf68a0c7021a05d977f3c96fe Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 25 Jun 2017 18:52:27 +0200 Subject: [PATCH 10/79] API refactoring --- src/Gist/Api/Client.php | 2 +- src/Gist/Command/CreateCommand.php | 43 ++++++++++++++------------- src/Gist/Command/UpdateCommand.php | 40 +++++++++++++------------ src/Gist/Controller/ApiController.php | 29 ++++++++++++++++++ src/Gist/Form/ApiCreateGistForm.php | 4 ++- src/Gist/Form/ApiUpdateGistForm.php | 1 + 6 files changed, 78 insertions(+), 41 deletions(-) diff --git a/src/Gist/Api/Client.php b/src/Gist/Api/Client.php index 29c26a0..b3055a5 100644 --- a/src/Gist/Api/Client.php +++ b/src/Gist/Api/Client.php @@ -19,7 +19,7 @@ class Client extends BaseClient const CREATE = '/en/api/create'; /** - * URI of updating + * URI of update * * @const string */ diff --git a/src/Gist/Command/CreateCommand.php b/src/Gist/Command/CreateCommand.php index 7aa7027..14fdd46 100644 --- a/src/Gist/Command/CreateCommand.php +++ b/src/Gist/Command/CreateCommand.php @@ -7,6 +7,8 @@ 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; /** * class CreateCommand. @@ -27,8 +29,9 @@ class CreateCommand extends Command ->addArgument('input', InputArgument::REQUIRED, 'Input') ->addArgument('type', InputArgument::OPTIONAL, 'Type', 'text') ->addOption('title', 't', InputOption::VALUE_REQUIRED, 'Title of the gist') - ->addOption('show-url', 'u', InputOption::VALUE_NONE, 'Display only the gist url') - ->addOption('show-id', 'i', InputOption::VALUE_NONE, 'Display only the gist Id') + ->addOption('all', 'a', InputOption::VALUE_NONE, 'Display all the response') + ->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(<<--title, -t Defines a title - - --show-id, -i - Display only the Id of the gist - --show-url, -u - Display only the url of the gist + --id, -i + Display only the id of the gist + + --all, -a + Display all the response + + --json, -j + Format the response to json EOF ); } @@ -58,11 +64,10 @@ EOF */ protected function execute(InputInterface $input, OutputInterface $output) { - //$output->writeln(sprintf('%s bar.', 'test')); - $file = $input->getArgument('input'); $type = $input->getArgument('type'); $title = $input->getOption('title'); + $json = $input->getOption('json'); if ($file === '-') { $content = file_get_contents('php://stdin'); @@ -94,19 +99,17 @@ EOF $gist = $this->getSilexApplication()['api_client']->create($title, $type, $content); - if ($input->getOption('show-url')) { - $output->writeln($gist['url']); - - return true; + if ($input->getOption('id')) { + $id = isset($gist['gist']['id']) ? $gist['gist']['id'] : $gist['gist']['Id']; + $result = $json ? json_encode(array('id' => $id)) : $id; + } 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($gist['gist']['Id']); - - return true; - } - - $output->writeln(json_encode($gist)); + $output->writeln($result); } /** diff --git a/src/Gist/Command/UpdateCommand.php b/src/Gist/Command/UpdateCommand.php index ef09a00..a48ec14 100644 --- a/src/Gist/Command/UpdateCommand.php +++ b/src/Gist/Command/UpdateCommand.php @@ -7,6 +7,7 @@ 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 Symfony\Component\Yaml\Yaml; /** * class UpdateCommand. @@ -26,8 +27,9 @@ class UpdateCommand extends Command ->setDescription('Update a gist using the API') ->addArgument('input', InputArgument::REQUIRED, 'Input') ->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('show-id', 'i', InputOption::VALUE_NONE, 'Display only the gist Id') + ->addOption('all', 'a', InputOption::VALUE_NONE, 'Display all the response') + ->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(<<--gist Defines the Gist to update by using its Id or its File - --show-id, -i - Display only the Id of the gist + --id, -i + Display only the id of the gist - --show-url, -u - Display only the url of the gist + --all, -a + Display all the response + + --json, -j + Format the response to json EOF ); } @@ -57,10 +62,9 @@ EOF */ protected function execute(InputInterface $input, OutputInterface $output) { - //$output->writeln(sprintf('%s bar.', 'test')); - $file = $input->getArgument('input'); $gist = $input->getOption('gist'); + $json = $input->getOption('json'); if ($file === '-') { $content = file_get_contents('php://stdin'); @@ -86,19 +90,17 @@ EOF $gist = $this->getSilexApplication()['api_client']->update($gist, $content); - if ($input->getOption('show-url')) { - $output->writeln($gist['url']); - - return true; + if ($input->getOption('id')) { + $id = isset($gist['gist']['id']) ? $gist['gist']['id'] : $gist['gist']['Id']; + $result = $json ? json_encode(array('id' => $id)) : $id; + } 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($gist['gist']['Id']); - - return true; - } - - $output->writeln(json_encode($gist)); + $output->writeln($result); } /** diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index 5b86bbe..1fd08d9 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -16,6 +16,13 @@ use Gist\Form\ApiUpdateGistForm; */ class ApiController extends Controller { + /** + * Creates a gist. + * + * @param Request $request + * + * @return JsonResponse + */ public function createAction(Request $request) { $app = $this->getApp(); @@ -56,6 +63,14 @@ class ApiController extends Controller return $this->invalidRequestResponse('Invalid field(s)'); } + /** + * Updates a gist. + * + * @param Request $request + * @param string $gist + * + * @return JsonResponse + */ public function updateAction(Request $request, $gist) { $app = $this->getApp(); @@ -106,6 +121,13 @@ class ApiController extends Controller return $this->invalidRequestResponse('Invalid field(s)'); } + /** + * Builds an invalid method response. + * + * @param mixed $message + * + * @return JsonResponse + */ protected function invalidMethodResponse($message = null) { $data = [ @@ -116,6 +138,13 @@ class ApiController extends Controller return new JsonResponse($data, 405); } + /** + * Builds an invalid request response. + * + * @param mixed $message + * + * @return JsonResponse + */ protected function invalidRequestResponse($message = null) { $data = [ diff --git a/src/Gist/Form/ApiCreateGistForm.php b/src/Gist/Form/ApiCreateGistForm.php index 27f3e4b..436f78a 100644 --- a/src/Gist/Form/ApiCreateGistForm.php +++ b/src/Gist/Form/ApiCreateGistForm.php @@ -16,7 +16,9 @@ class ApiCreateGistForm extends CreateGistForm { parent::build($options); - $this->builder->remove('cipher'); + $this->builder + ->remove('cipher') + ->remove('file'); return $this->builder; } diff --git a/src/Gist/Form/ApiUpdateGistForm.php b/src/Gist/Form/ApiUpdateGistForm.php index 2594d59..bc058e3 100644 --- a/src/Gist/Form/ApiUpdateGistForm.php +++ b/src/Gist/Form/ApiUpdateGistForm.php @@ -18,6 +18,7 @@ class ApiUpdateGistForm extends ApiCreateGistForm $this->builder ->remove('title') + ->remove('file') ->remove('type'); return $this->builder; From 80b3c0bbdb1507a2c4a93941faf3d849eff3960b Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 25 Jun 2017 19:13:27 +0200 Subject: [PATCH 11/79] Merge stash --- app/config/config.yml.dist | 1 + app/config/routing.yml | 8 +- src/Gist/Api/Client.php | 9 +- src/Gist/Controller/ApiController.php | 140 ++++++++++++++++---- src/Gist/Controller/LoginController.php | 4 +- src/Gist/Controller/MyController.php | 19 +++ src/Gist/Model/Gist.php | 22 +++ src/Gist/Model/User.php | 6 +- src/Gist/Resources/config/propel/schema.xml | 1 + src/Gist/Resources/views/My/my.html.twig | 18 +++ src/Gist/Resources/views/base.html.twig | 6 +- src/Gist/Service/SaltGenerator.php | 18 ++- src/Gist/Service/UserProvider.php | 1 + web/app/js/app.js | 4 + 14 files changed, 216 insertions(+), 41 deletions(-) diff --git a/app/config/config.yml.dist b/app/config/config.yml.dist index b8af280..b988285 100644 --- a/app/config/config.yml.dist +++ b/app/config/config.yml.dist @@ -6,6 +6,7 @@ security: login_required_to_view_gist: false login_required_to_view_embeded_gist: false api: + enabled: true base_url: 'https://gist.deblan.org/' data: path: data/git diff --git a/app/config/routing.yml b/app/config/routing.yml index 666ca81..e3421cf 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -57,10 +57,14 @@ revisions: path: /revs/{gist} defaults: {_controller: Gist\Controller\ViewController::revisionsAction, _locale: en} +api_list: + path: /api/list/{apiKey} + defaults: {_controller: Gist\Controller\ApiController::listAction, _locale: en} + api_create: - path: /api/create + path: /api/create/{apiKey} defaults: {_controller: Gist\Controller\ApiController::createAction, _locale: en} api_update: - path: /api/update/{gist} + path: /api/update/{gist}/{apiKey} defaults: {_controller: Gist\Controller\ApiController::updateAction, _locale: en} diff --git a/src/Gist/Api/Client.php b/src/Gist/Api/Client.php index b3055a5..830416f 100644 --- a/src/Gist/Api/Client.php +++ b/src/Gist/Api/Client.php @@ -12,25 +12,26 @@ use GuzzleHttp\Client as BaseClient; class Client extends BaseClient { /** - * URI of creation - * + * URI of creation. + * * @const string */ const CREATE = '/en/api/create'; /** - * URI of update + * URI of update. * * @const string */ const UPDATE = '/en/api/update/{gist}'; /** - * Creates a gist + * Creates a gist. * * @param string $title The title * @param string $type The type * @param string $content The content + * * @return array */ public function create($title, $type, $content) diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index 1fd08d9..a27ac1a 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -8,6 +8,8 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Gist\Form\ApiCreateGistForm; use Gist\Model\GistQuery; use Gist\Form\ApiUpdateGistForm; +use GitWrapper\GitException; +use Gist\Model\UserQuery; /** * Class ApiController. @@ -17,16 +19,73 @@ use Gist\Form\ApiUpdateGistForm; class ApiController extends Controller { /** - * Creates a gist. + * Lists gists. * * @param Request $request + * @param string $apiKey * * @return JsonResponse */ - public function createAction(Request $request) + public function listAction(Request $request, $apiKey) { $app = $this->getApp(); + if (false === $app['settings']['api']['enabled']) { + return new Response('', 403); + } + + if (false === $this->isValidApiKey($apiKey)) { + return $this->invalidApiKeyResponse(); + } + + if (false === $request->isMethod('get')) { + return $this->invalidMethodResponse('GET method is required.'); + } + + $gists = GistQuery::create()->find(); + $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)) { + return $this->invalidApiKeyResponse(); + } + if (false === $request->isMethod('post')) { return $this->invalidMethodResponse('POST method is required.'); } @@ -48,16 +107,16 @@ class ApiController extends Controller $history = $app['gist']->getHistory($gist); - return new JsonResponse(array( - 'url' => $request->getSchemeAndHttpHost().$app['url_generator']->generate( - 'view', - array( - 'gist' => $gist->getFile(), - 'commit' => array_pop($history)['commit'], - ) - ), - 'gist' => $gist->toArray(), - )); + $data = $gist->toArray(); + $data['url'] = $request->getSchemeAndHttpHost().$app['url_generator']->generate( + 'view', + array( + 'gist' => $gist->getFile(), + 'commit' => array_pop($history)['commit'], + ) + ); + + return new JsonResponse($data); } return $this->invalidRequestResponse('Invalid field(s)'); @@ -67,14 +126,23 @@ class ApiController extends Controller * Updates a gist. * * @param Request $request - * @param string $gist + * @param string $gist + * @param string $apiKey * * @return JsonResponse */ - public function updateAction(Request $request, $gist) + public function updateAction(Request $request, $gist, $apiKey) { $app = $this->getApp(); + if (false === $app['settings']['api']['enabled']) { + return new Response('', 403); + } + + if (false === $this->isValidApiKey($apiKey)) { + return $this->invalidApiKeyResponse(); + } + if (false === $request->isMethod('post')) { return $this->invalidMethodResponse('POST method is required.'); } @@ -106,21 +174,38 @@ class ApiController extends Controller $history = $app['gist']->getHistory($gist); - return new JsonResponse(array( - 'url' => $request->getSchemeAndHttpHost().$app['url_generator']->generate( - 'view', - array( - 'gist' => $gist->getFile(), - 'commit' => array_pop($history)['commit'], - ) - ), - 'gist' => $gist->toArray(), - )); + $data = $gist->toArray(); + $data['url'] = $request->getSchemeAndHttpHost().$app['url_generator']->generate( + 'view', + array( + 'gist' => $gist->getFile(), + 'commit' => array_pop($history)['commit'], + ) + ); + + return new JsonResponse($data); } return $this->invalidRequestResponse('Invalid field(s)'); } + /** + * 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. * @@ -154,4 +239,11 @@ class ApiController extends Controller return new JsonResponse($data, 400); } + + protected function isValidApiKey($apiKey) + { + return !empty($apiKey) && UserQuery::create() + ->filterByApiKey($apiKey) + ->count() === 1; + } } diff --git a/src/Gist/Controller/LoginController.php b/src/Gist/Controller/LoginController.php index a45d1a3..f835306 100644 --- a/src/Gist/Controller/LoginController.php +++ b/src/Gist/Controller/LoginController.php @@ -26,7 +26,7 @@ class LoginController extends Controller { $app = $this->getApp(); - if (false === $app['settings']['enable_registration']) { + if (false === $app['settings']['security']['enable_registration']) { return new Response('', 403); } @@ -78,7 +78,7 @@ class LoginController extends Controller { $app = $this->getApp(); - if (false === $app['settings']['enable_login']) { + if (false === $app['settings']['security']['enable_login']) { return new Response('', 403); } diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index aa113c8..375bdd2 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -58,6 +58,24 @@ class MyController extends Controller $gists = $this->getUser()->getGistsPager($page, $options); + $apiKey = $this->getUser()->getApiKey(); + + if (empty($apiKey)) { + $regenerateApiKey = true; + } 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')) { $deleteForm->handleRequest($request); $passwordForm->handleRequest($request); @@ -104,6 +122,7 @@ class MyController extends Controller array( 'gists' => $gists, 'page' => $page, + 'apiKey' => $apiKey, 'deleteForm' => $deleteForm->createView(), 'filterForm' => $filterForm->createView(), 'passwordForm' => $passwordForm->createView(), diff --git a/src/Gist/Model/Gist.php b/src/Gist/Model/Gist.php index 23a4809..86efe42 100644 --- a/src/Gist/Model/Gist.php +++ b/src/Gist/Model/Gist.php @@ -3,6 +3,7 @@ namespace Gist\Model; use Gist\Model\Base\Gist as BaseGist; +use Propel\Runtime\Map\TableMap; /** * Class Gist. @@ -86,4 +87,25 @@ class Gist extends BaseGist 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; + } } diff --git a/src/Gist/Model/User.php b/src/Gist/Model/User.php index e5d483b..b57d03e 100644 --- a/src/Gist/Model/User.php +++ b/src/Gist/Model/User.php @@ -54,7 +54,7 @@ class User extends BaseUser implements UserInterface * * @return Propel\Runtime\Util\PropelModelPager */ - public function getGistsPager($page, $options = array(), $maxPerPage = 10) + public function getGistsPager($page, $options = array(), $maxPerPage = 10) { $query = GistQuery::create() ->filterByUser($this) @@ -63,11 +63,11 @@ class User extends BaseUser implements UserInterface if (!empty($options['type']) && $options['type'] !== 'all') { $query->filterByType($options['type']); } - + if (!empty($options['title'])) { $query->filterByTitle('%'.$options['title'].'%', Criteria::LIKE); } - + if (!empty($options['cipher']) && $options['cipher'] !== 'anyway') { $bools = array( 'yes' => true, diff --git a/src/Gist/Resources/config/propel/schema.xml b/src/Gist/Resources/config/propel/schema.xml index ce79ebb..8caac4e 100644 --- a/src/Gist/Resources/config/propel/schema.xml +++ b/src/Gist/Resources/config/propel/schema.xml @@ -22,6 +22,7 @@ + diff --git a/src/Gist/Resources/views/My/my.html.twig b/src/Gist/Resources/views/My/my.html.twig index 2e65a3b..9f954bb 100644 --- a/src/Gist/Resources/views/My/my.html.twig +++ b/src/Gist/Resources/views/My/my.html.twig @@ -230,6 +230,24 @@
  • + + {% if app.settings.api.enabled %} +
    +
    + {{ 'api.title'|trans }} +
    +
    +
    + +

    + + +

    + +
    +
    +
    + {% endif %}
    {% endblock %} diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index 046d5f1..9146d00 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -1,6 +1,6 @@ {% set theme_settings = app.settings.theme %} -{% set security_dettings = app.settings.security %} +{% set security_settings = app.settings.security %} {% block css %} @@ -56,14 +56,14 @@ {{ 'app.menu.my.logout.title'|trans }} - {% elseif security_dettings.enable_login %} + {% elseif security_settings.enable_login %}
  • {{ 'app.menu.my.login.title'|trans }}
  • - {% if security_dettings.enable_registration %} + {% if security_settings.enable_registration %}
  • {{ 'app.menu.my.register.title'|trans }} diff --git a/src/Gist/Service/SaltGenerator.php b/src/Gist/Service/SaltGenerator.php index f86a0e0..a3143c2 100644 --- a/src/Gist/Service/SaltGenerator.php +++ b/src/Gist/Service/SaltGenerator.php @@ -18,18 +18,30 @@ class SaltGenerator * * @return string */ - public function generate($length = 32) + public function generate($length = 32, $isApiKey = false) { if (!is_numeric($length)) { throw new InvalidArgumentException('Paramter length must be a valid integer.'); } 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')) { - 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.'); diff --git a/src/Gist/Service/UserProvider.php b/src/Gist/Service/UserProvider.php index beab8e1..b0f1813 100644 --- a/src/Gist/Service/UserProvider.php +++ b/src/Gist/Service/UserProvider.php @@ -126,6 +126,7 @@ class UserProvider implements UserProviderInterface $user ->setRoles('ROLE_USER') ->setPassword($this->encoder->encodePassword($password, $user->getSalt())) + ->setApiKey($this->saltGenerator->generate(32, true)) ->save(); return $user; diff --git a/web/app/js/app.js b/web/app/js/app.js index a4d64d4..671d102 100644 --- a/web/app/js/app.js +++ b/web/app/js/app.js @@ -98,6 +98,10 @@ var myEvents = function() { $('#form-deletion form').submit(); } }); + + $(document).on('change keyup keydown', '#form-api-key', function() { + $(this).val($(this).data('key')); + }); } var mainEditorEvents = function() { From ffe3540565c0061eb8fa241d6a1ccd80808399ee Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 25 Jun 2017 23:06:24 +0200 Subject: [PATCH 12/79] API key --- app/config/config.yml.dist | 3 +++ src/Gist/Controller/ApiController.php | 10 +++++++--- src/Gist/Controller/Controller.php | 10 ++++++++-- src/Gist/Controller/MyController.php | 4 +++- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/config/config.yml.dist b/app/config/config.yml.dist index b988285..c9845ec 100644 --- a/app/config/config.yml.dist +++ b/app/config/config.yml.dist @@ -7,7 +7,10 @@ security: 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: diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index a27ac1a..1d974dd 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -34,7 +34,7 @@ class ApiController extends Controller return new Response('', 403); } - if (false === $this->isValidApiKey($apiKey)) { + if (false === $this->isValidApiKey($apiKey, true)) { return $this->invalidApiKeyResponse(); } @@ -240,9 +240,13 @@ class ApiController extends Controller return new JsonResponse($data, 400); } - protected function isValidApiKey($apiKey) + protected function isValidApiKey($apiKey, $required = false) { - return !empty($apiKey) && UserQuery::create() + if (empty($apiKey)) { + return !$required; + } + + return UserQuery::create() ->filterByApiKey($apiKey) ->count() === 1; } diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index c96d8d0..e166f39 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -13,7 +13,7 @@ use Symfony\Component\HttpFoundation\Response; * * @author Simon Vieille */ -class Controller +abstract class Controller { /** * @var Application @@ -128,12 +128,18 @@ class Controller /** * Returns the connected user. * + * @param Request $request An API request + * * @return mixed */ - public function getUser() + public function getUser(Request $request = null) { $app = $this->getApp(); + if (!empty($request)) { + + } + $securityContext = $app['security.token_storage']; $securityToken = $securityContext->getToken(); diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index 375bdd2..e54a76c 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -62,7 +62,9 @@ class MyController extends Controller if (empty($apiKey)) { $regenerateApiKey = true; - } elseif ($request->request->get('apiKey') === $apiKey && $request->request->has('generateApiKey')) { + } + // FIXME: CSRF issue!. + elseif ($request->request->get('apiKey') === $apiKey && $request->request->has('generateApiKey')) { $regenerateApiKey = true; } else { $regenerateApiKey = false; From 91cdb2341caf6e31b96d1cc1b02450b2bd777ecb Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 25 Jun 2017 23:09:34 +0200 Subject: [PATCH 13/79] Favicon --- src/Gist/Resources/views/base.html.twig | 14 ++++++++------ web/favicon.png | Bin 0 -> 570 bytes 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 web/favicon.png diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index 9146d00..aedcedb 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -4,23 +4,25 @@ {% block css %} - - + + {% if theme_settings.name == 'dark' %} - + {% else %} - + {% endif %} - + {% endblock %} {% block metas %} - + {% endblock %} + + {{ 'app.title_prefix'|trans }}{% block title %}{% endblock %} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..db26dfd41b77e121d403a44e65aecdcd71dc963d GIT binary patch literal 570 zcmV-A0>%A_P)!dZ6pl7+d=bZPs@3~i38jVJd<2X9E z2-7q})o~o%wr%4!008-aniW;hUX73yaWkMh@aYbG0Ibb`jYnQp+uC*6e>vvC?%BHK{##l{&f$4k8jpFJm>>(d~}b`AJ(opkm~>; z0E*lFY3t=4f-{{oR!TtKK{Y~m;M3o80C@8J6s?f~FnIc%;Kv40sF5bp6(`q5XpmJ*hH0ANA5ONjFit@QkN^Mx07*qo IM6N<$f?6r{Z2$lO literal 0 HcmV?d00001 From a478fb3de5ccaec34e69f18731ca3a4ab62e5a72 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 11 Aug 2017 10:57:57 +0200 Subject: [PATCH 14/79] Fix issue with locale cookie --- app/bootstrap.php.d/30-trans.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bootstrap.php.d/30-trans.php b/app/bootstrap.php.d/30-trans.php index e18aff5..9ec8a36 100644 --- a/app/bootstrap.php.d/30-trans.php +++ b/app/bootstrap.php.d/30-trans.php @@ -50,7 +50,7 @@ $app->get('/', function (Request $request) use ($app) { $foundLocale = $app['translator']->getLocale(); foreach ($app['locales'] as $locale) { - if ($cookie === $locale || $accept->has($locale)) { + if ($cookieValue === $locale || $accept->has($locale)) { $foundLocale = $locale; break; } From f6e48377760c033363b205afc193cd62758773a0 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 23 Aug 2017 17:20:23 +0200 Subject: [PATCH 15/79] Implementation of Api action "list" --- app/bootstrap.php.d/60-api.php | 8 ++- app/config/routing.yml | 6 +-- app/console | 2 + src/Gist/Api/Client.php | 77 ++++++++++++++++++++++++++- src/Gist/Command/ListCommand.php | 59 ++++++++++++++++++++ src/Gist/Controller/ApiController.php | 4 +- 6 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 src/Gist/Command/ListCommand.php diff --git a/app/bootstrap.php.d/60-api.php b/app/bootstrap.php.d/60-api.php index 4892f39..ba94758 100644 --- a/app/bootstrap.php.d/60-api.php +++ b/app/bootstrap.php.d/60-api.php @@ -3,5 +3,11 @@ use Gist\Api\Client; $app['api_client'] = $app->share(function ($app) { - return new Client(['base_uri' => rtrim($app['settings']['api']['base_url'], '/')]); + $client = new Client(['base_uri' => rtrim($app['settings']['api']['base_url'], '/')]); + + if (!empty($app['settings']['api']['client']['api_key'])) { + $client->setApiToken($app['settings']['api']['client']['api_key']); + } + + return $client; }); diff --git a/app/config/routing.yml b/app/config/routing.yml index e3421cf..2deef13 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -59,12 +59,12 @@ revisions: api_list: path: /api/list/{apiKey} - defaults: {_controller: Gist\Controller\ApiController::listAction, _locale: en} + defaults: {_controller: Gist\Controller\ApiController::listAction, _locale: en, apiKey: null} 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: path: /api/update/{gist}/{apiKey} - defaults: {_controller: Gist\Controller\ApiController::updateAction, _locale: en} + defaults: {_controller: Gist\Controller\ApiController::updateAction, _locale: en, apiKey: null} diff --git a/app/console b/app/console index eef6670..dd14b19 100755 --- a/app/console +++ b/app/console @@ -2,6 +2,7 @@ add(new CreateCommand()); +$app['console']->add(new ListCommand()); $app['console']->add(new UpdateCommand()); $app['console']->add(new StatsCommand()); $app['console']->add(new UserCreateCommand()); diff --git a/src/Gist/Api/Client.php b/src/Gist/Api/Client.php index 830416f..548839f 100644 --- a/src/Gist/Api/Client.php +++ b/src/Gist/Api/Client.php @@ -25,6 +25,20 @@ class Client extends BaseClient */ const UPDATE = '/en/api/update/{gist}'; + /** + * URI of list. + * + * @const string + */ + const LIST = '/en/api/list'; + + /** + * The API token. + * + * @var string|null + */ + protected $apiToken; + /** * Creates a gist. * @@ -37,7 +51,7 @@ class Client extends BaseClient public function create($title, $type, $content) { $response = $this->post( - self::CREATE, + $this->mergeToken(self::CREATE), array( 'form_params' => array( 'form' => array( @@ -67,7 +81,7 @@ class Client extends BaseClient public function update($gist, $content) { $response = $this->post( - str_replace('{gist}', $gist, self::UPDATE), + str_replace('{gist}', $gist, $this->mergeToken(self::LIST)), array( 'form_params' => array( 'form' => array( @@ -83,4 +97,63 @@ class Client extends BaseClient 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->mergeToken(self::LIST)); + + if ($response->getStatusCode() === 200) { + return json_decode($response->getBody()->getContents(), true); + } + + return []; + } + + /* + * Merges the API token with the given url.. + * + * @param string $url + * + * @return string + */ + public function mergeToken($url) + { + if (empty($this->apiToken)) { + return $url; + } + + return rtrim($url, '/').'/'.$this->apiToken; + } + + /* + * Set the value of "apiToken". + * + * @param string|null $apiToken + * + * @return Client + */ + public function setApiToken($apiToken) + { + $this->apiToken = $apiToken; + + return $this; + } + + /* + * Get the value of "apiToken". + * + * @return string|null + */ + public function getApiToken() + { + return $this->apiToken; + } } diff --git a/src/Gist/Command/ListCommand.php b/src/Gist/Command/ListCommand.php new file mode 100644 index 0000000..a0c99aa --- /dev/null +++ b/src/Gist/Command/ListCommand.php @@ -0,0 +1,59 @@ + + */ +class ListCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('list') + ->setDescription('Listing 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(); + } +} diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index 1d974dd..f5fe881 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -82,7 +82,7 @@ class ApiController extends Controller return new Response('', 403); } - if (false === $this->isValidApiKey($apiKey)) { + if (false === $this->isValidApiKey($apiKey, (bool) $app['settings']['api']['api_key_required'])) { return $this->invalidApiKeyResponse(); } @@ -139,7 +139,7 @@ class ApiController extends Controller return new Response('', 403); } - if (false === $this->isValidApiKey($apiKey)) { + if (false === $this->isValidApiKey($apiKey, (bool) $app['settings']['api']['api_key_required'])) { return $this->invalidApiKeyResponse(); } From 87348c83356bebafadef3deaa4043c841919f3ff Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 23 Aug 2017 19:32:56 +0200 Subject: [PATCH 16/79] Implementation of Api action "delete" --- app/bootstrap.php.d/60-api.php | 2 +- app/config/routing.yml | 4 ++ src/Gist/Api/Client.php | 67 ++++++++++++++++++--------- src/Gist/Controller/ApiController.php | 61 +++++++++++++++++++++++- src/Gist/Service/UserProvider.php | 14 ++++++ 5 files changed, 124 insertions(+), 24 deletions(-) diff --git a/app/bootstrap.php.d/60-api.php b/app/bootstrap.php.d/60-api.php index ba94758..d630058 100644 --- a/app/bootstrap.php.d/60-api.php +++ b/app/bootstrap.php.d/60-api.php @@ -6,7 +6,7 @@ $app['api_client'] = $app->share(function ($app) { $client = new Client(['base_uri' => rtrim($app['settings']['api']['base_url'], '/')]); if (!empty($app['settings']['api']['client']['api_key'])) { - $client->setApiToken($app['settings']['api']['client']['api_key']); + $client->setApiKey($app['settings']['api']['client']['api_key']); } return $client; diff --git a/app/config/routing.yml b/app/config/routing.yml index 2deef13..49ad3f4 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -68,3 +68,7 @@ api_create: api_update: path: /api/update/{gist}/{apiKey} 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} diff --git a/src/Gist/Api/Client.php b/src/Gist/Api/Client.php index 548839f..82ed6cd 100644 --- a/src/Gist/Api/Client.php +++ b/src/Gist/Api/Client.php @@ -25,6 +25,13 @@ class Client extends BaseClient */ const UPDATE = '/en/api/update/{gist}'; + /** + * URI of delete. + * + * @const string + */ + const DELETE = '/en/api/delete/{gist}'; + /** * URI of list. * @@ -33,17 +40,17 @@ class Client extends BaseClient const LIST = '/en/api/list'; /** - * The API token. + * The API key. * * @var string|null */ - protected $apiToken; + protected $apiKey; /** * Creates a gist. * - * @param string $title The title - * @param string $type The type + * @param string $title The title + * @param string $type The type * @param string $content The content * * @return array @@ -51,7 +58,7 @@ class Client extends BaseClient public function create($title, $type, $content) { $response = $this->post( - $this->mergeToken(self::CREATE), + $this->mergeApiKey(self::CREATE), array( 'form_params' => array( 'form' => array( @@ -71,9 +78,9 @@ 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 * * @return array @@ -81,7 +88,7 @@ class Client extends BaseClient public function update($gist, $content) { $response = $this->post( - str_replace('{gist}', $gist, $this->mergeToken(self::LIST)), + str_replace('{gist}', $gist, $this->mergeApiKey(self::LIST)), array( 'form_params' => array( 'form' => array( @@ -99,16 +106,34 @@ class Client extends BaseClient } /** - * Lists the user's gists. + * 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->mergeToken(self::LIST)); + $response = $this->get($this->mergeApiKey(self::LIST)); if ($response->getStatusCode() === 200) { return json_decode($response->getBody()->getContents(), true); @@ -118,42 +143,42 @@ class Client extends BaseClient } /* - * Merges the API token with the given url.. + * Merges the API key with the given url. * * @param string $url * * @return string */ - public function mergeToken($url) + public function mergeApiKey($url) { - if (empty($this->apiToken)) { + if (empty($this->apiKey)) { return $url; } - return rtrim($url, '/').'/'.$this->apiToken; + return rtrim($url, '/').'/'.$this->apiKey; } /* - * Set the value of "apiToken". + * Set the value of "apiKey". * - * @param string|null $apiToken + * @param string|null $apiKey * * @return Client */ - public function setApiToken($apiToken) + public function setApiKey($apiKey) { - $this->apiToken = $apiToken; + $this->apiKey = $apiKey; return $this; } /* - * Get the value of "apiToken". + * Get the value of "apiKey". * * @return string|null */ - public function getApiToken() + public function getApiKey() { - return $this->apiToken; + return $this->apiKey; } } diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index f5fe881..3013bab 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -42,7 +42,8 @@ class ApiController extends Controller return $this->invalidMethodResponse('GET method is required.'); } - $gists = GistQuery::create()->find(); + $user = $app['user.provider']->loadUserByApiKey($apiKey); + $gists = $user->getGists(); $data = array(); foreach ($gists as $gist) { @@ -102,8 +103,12 @@ class ApiController extends Controller $form->submit($request); if ($form->isValid()) { + $user = !empty($apiKey) ? $app['user.provider']->loadUserByApiKey($apiKey) : null; $gist = $app['gist']->create(new Gist(), $form->getData()); - $gist->setCipher(false)->save(); + $gist + ->setCipher(false) + ->setUser($user) + ->save(); $history = $app['gist']->getHistory($gist); @@ -189,6 +194,49 @@ class ApiController extends Controller 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. * @@ -240,6 +288,15 @@ class ApiController extends Controller 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)) { diff --git a/src/Gist/Service/UserProvider.php b/src/Gist/Service/UserProvider.php index b0f1813..e887b50 100644 --- a/src/Gist/Service/UserProvider.php +++ b/src/Gist/Service/UserProvider.php @@ -167,6 +167,20 @@ class UserProvider implements UserProviderInterface 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. * From ab58bdb82d720843ad21592c7976ae1fc06a745d Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 23 Aug 2017 19:54:58 +0200 Subject: [PATCH 17/79] Implementation of Api action "delete" --- app/console | 2 ++ src/Gist/Command/DeleteCommand.php | 48 +++++++++++++++++++++++++++ src/Gist/Command/ListCommand.php | 2 +- src/Gist/Controller/ApiController.php | 2 +- 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/Gist/Command/DeleteCommand.php diff --git a/app/console b/app/console index dd14b19..b1e12fb 100755 --- a/app/console +++ b/app/console @@ -5,6 +5,7 @@ use Gist\Command\CreateCommand; use Gist\Command\ListCommand; use Gist\Command\UpdateCommand; use Gist\Command\StatsCommand; +use Gist\Command\DeleteCommand; use Gist\Command\UserCreateCommand; use Gist\Command\Migration\UpgradeTo1p4p1Command; @@ -13,6 +14,7 @@ $app = require __DIR__.'/bootstrap.php'; $app['console']->add(new CreateCommand()); $app['console']->add(new ListCommand()); $app['console']->add(new UpdateCommand()); +$app['console']->add(new DeleteCommand()); $app['console']->add(new StatsCommand()); $app['console']->add(new UserCreateCommand()); $app['console']->add(new UpgradeTo1p4p1Command()); diff --git a/src/Gist/Command/DeleteCommand.php b/src/Gist/Command/DeleteCommand.php new file mode 100644 index 0000000..ec0ca31 --- /dev/null +++ b/src/Gist/Command/DeleteCommand.php @@ -0,0 +1,48 @@ + + */ +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: + --gist + 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' : 'An error occured.'); + } +} diff --git a/src/Gist/Command/ListCommand.php b/src/Gist/Command/ListCommand.php index a0c99aa..4c2f1f9 100644 --- a/src/Gist/Command/ListCommand.php +++ b/src/Gist/Command/ListCommand.php @@ -26,7 +26,7 @@ class ListCommand extends Command { $this ->setName('list') - ->setDescription('Listing gists using the API'); + ->setDescription('List gists using the API'); } /** diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index 3013bab..842bf99 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -216,7 +216,7 @@ class ApiController extends Controller } if (false === $request->isMethod('post')) { - // return $this->invalidMethodResponse('POST method is required.'); + return $this->invalidMethodResponse('POST method is required.'); } $user = $app['user.provider']->loadUserByApiKey($apiKey); From 4d2cf30de1bcda2dd1acb220a3878545af925d57 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Sep 2017 17:56:37 +0200 Subject: [PATCH 18/79] API: UI and command 'list' renamed with 'gists' --- app/locales/cn.yml | 5 ++ app/locales/de.yml | 5 ++ app/locales/en.yml | 6 ++ app/locales/es.yml | 5 ++ app/locales/fr.yml | 5 ++ src/Gist/Command/ListCommand.php | 2 +- src/Gist/Controller/MyController.php | 2 +- src/Gist/Resources/views/My/my.html.twig | 87 ++++++++++++++---------- 8 files changed, 78 insertions(+), 39 deletions(-) diff --git a/app/locales/cn.yml b/app/locales/cn.yml index 30c5aa7..adfe2d8 100644 --- a/app/locales/cn.yml +++ b/app/locales/cn.yml @@ -20,6 +20,11 @@ app: my: title: '我的 Gist' nothing: '这家伙很懒,暂时没有内容' + api: + title: 'API' + warning: 'Keep it secret!' + form: + generate: 'Regenerate' gist: untitled: '未命名' diff --git a/app/locales/de.yml b/app/locales/de.yml index 42cc012..c91934d 100644 --- a/app/locales/de.yml +++ b/app/locales/de.yml @@ -20,6 +20,11 @@ app: my: title: 'Meine Gists' nothing: 'Nichts zu finden (momentan)!' + api: + title: 'API' + warning: 'Keep it secret!' + form: + generate: 'Regenerate' gist: untitled: 'Ohne Titel' diff --git a/app/locales/en.yml b/app/locales/en.yml index 51630d3..ff80822 100644 --- a/app/locales/en.yml +++ b/app/locales/en.yml @@ -20,6 +20,12 @@ app: my: title: 'My gists' nothing: 'Nothing yet!' + api: + title: 'API' + warning: 'Keep it secret!' + form: + generate: 'Regenerate' + gist: untitled: 'Untitled' diff --git a/app/locales/es.yml b/app/locales/es.yml index 75cfe90..2d8176b 100644 --- a/app/locales/es.yml +++ b/app/locales/es.yml @@ -20,6 +20,11 @@ app: my: title: 'Mis Gists' nothing: 'Nada por ahora.' + api: + title: 'API' + warning: 'Keep it secret!' + form: + generate: 'Regenerate' gist: untitled: 'Sin título' diff --git a/app/locales/fr.yml b/app/locales/fr.yml index 7674d1b..8741cf5 100644 --- a/app/locales/fr.yml +++ b/app/locales/fr.yml @@ -20,6 +20,11 @@ app: my: title: 'Mes Gists' nothing: 'Rien pour le moment !' + api: + title: 'API' + warning: 'Gardez-la secrète !' + form: + generate: 'Regénérer' gist: untitled: 'Sans titre' diff --git a/src/Gist/Command/ListCommand.php b/src/Gist/Command/ListCommand.php index 4c2f1f9..878b443 100644 --- a/src/Gist/Command/ListCommand.php +++ b/src/Gist/Command/ListCommand.php @@ -25,7 +25,7 @@ class ListCommand extends Command protected function configure() { $this - ->setName('list') + ->setName('gists') ->setDescription('List gists using the API'); } diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index e54a76c..d59f315 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -63,7 +63,7 @@ class MyController extends Controller if (empty($apiKey)) { $regenerateApiKey = true; } - // FIXME: CSRF issue!. + // FIXME: CSRF issue! elseif ($request->request->get('apiKey') === $apiKey && $request->request->has('generateApiKey')) { $regenerateApiKey = true; } else { diff --git a/src/Gist/Resources/views/My/my.html.twig b/src/Gist/Resources/views/My/my.html.twig index 9f954bb..9ccbbc7 100644 --- a/src/Gist/Resources/views/My/my.html.twig +++ b/src/Gist/Resources/views/My/my.html.twig @@ -205,49 +205,62 @@ -
    -
    - {{ 'login.login.form.password.placeholder'|trans }} -
    -
    -
    -
    -

    - {{ form_errors(passwordForm.currentPassword) }} - {{ form_widget(passwordForm.currentPassword) }} -

    + {% set apiEnabled = app.settings.api.enabled %} -

    - {{ form_errors(passwordForm.newPassword) }} - {{ form_widget(passwordForm.newPassword) }} -

    +
    +
    +
    +
    + {{ 'login.login.form.password.placeholder'|trans }} +
    +
    +
    + +

    + {{ form_errors(passwordForm.currentPassword) }} + {{ form_widget(passwordForm.currentPassword) }} +

    -

    - {{ form_rest(passwordForm) }} - -

    - -
    -
    -
    +

    + {{ form_errors(passwordForm.newPassword) }} + {{ form_widget(passwordForm.newPassword) }} +

    - {% if app.settings.api.enabled %} -
    -
    - {{ 'api.title'|trans }} -
    -
    -
    -
    -

    - - -

    -
    +

    + {{ form_rest(passwordForm) }} + +

    + +
    - {% endif %} + {% if apiEnabled %} +
    +
    +
    + {{ 'my.api.title'|trans }} +
    +
    +
    +

    {{ 'my.api.warning'|trans|raw }}

    + +
    +
    +

    + +

    +

    + +

    +
    +
    +
    +
    +
    +
    + {% endif %} +
    {% endblock %} From d441d7e834b82fcae5651d33f2ca924c797aeeb1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Sep 2017 18:23:30 +0200 Subject: [PATCH 19/79] API list: limit of 15 results --- src/Gist/Controller/ApiController.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index 842bf99..89e18e1 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -10,6 +10,7 @@ use Gist\Model\GistQuery; use Gist\Form\ApiUpdateGistForm; use GitWrapper\GitException; use Gist\Model\UserQuery; +use Propel\Runtime\ActiveQuery\Criteria; /** * Class ApiController. @@ -43,7 +44,12 @@ class ApiController extends Controller } $user = $app['user.provider']->loadUserByApiKey($apiKey); - $gists = $user->getGists(); + + $criteria = GistQuery::create() + ->limit(15) + ->orderById(Criteria::DESC); + + $gists = $user->getGists($criteria); $data = array(); foreach ($gists as $gist) { From 43fd509d6910f2671bfe5452e299f4a46dc406f1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 21 Sep 2017 18:45:45 +0200 Subject: [PATCH 20/79] Documentation --- README.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ddf204c..a9e1493 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,12 @@ If your version is less than v1.4.2, run: `test -d app && git add app && git com $ make update $ make propel -If you upgrade to v1.4.1, run: `app/console migrate:to:v1.4.1`. +If you upgrade to v1.4.1 or more: `app/console migrate:to:v1.4.1`. If you upgrade to v1.4.4 or more, the configuration is moved to a `app/config/config.yml`: `$ cp app/config/config.yml.dist app/config/config.yml` and see the [configuration section](#configuration) for more information. +If you upgrade to v1.7.0 or more, see the [configuration section](#configurationh) for more information about new options. + Configuration ------------- @@ -173,6 +175,12 @@ Edit `app/config/config.yml`. * `git.path`: The path of `git`. * `theme.name`: the name of the theme (`dark` or `light`) +### Version >= v1.7.0 + +* `api.enabled`: defines if the API is enabled (`true` or `false`) +* `api.api_key_required`: defines if the API key is required to access the API (`true` or `false`) +* `api.client.api_key`: defines the client API key (`string`) + Makefile -------- @@ -187,7 +195,9 @@ A Makefile is provided to automate some tasks. API --- -### Create a new gist +### Version < v1.7.0 + +#### Create a new gist **POST** /{locale}/api/create Params: @@ -218,7 +228,7 @@ Params: } ``` -### Update an existing gist +#### Update an existing gist **POST** /{locale}/api/update/{id} Params: @@ -247,6 +257,115 @@ Params: } ``` +### Version >= v1.7.0 + +Invalid response codes: + +* Code `401`: Unauthorized +* Code `403`: API not enabled +* Code `405`: Method Not Allowed +* Code `400`: Bad Request + +#### List gists + +**GET** /{locale}/api/list/{apiToken} + +Response example: + +```javascript +[ + { + "id": 66, + "title": "test prod", + "cipher": false, + "type": "javascript", + "file": "55abcfa7771e0", + "createdAt": "2015-07-19T16:26:15Z", + "updatedAt": "2015-07-19T16:30:15Z" + "url": "https:\/\/gist.deblan.org\/en\/view\/55abcfa7771e0\/abcgi72967dd95e3461490dcaa310d728d6adef", + }, + { + "id": 67, + "title": "test prod 2", + "cipher": false, + "type": "javascript", + "file": "xyzbcfa7771e0", + "createdAt": "2015-08-19T16:26:15Z", + "updatedAt": "2015-08-19T16:30:15Z" + "url": "https:\/\/gist.deblan.org\/en\/view\/5byzbcfa7771e0\/def72967dd95e346koq0dcaa310d728d6artu", + }, + ... +] +``` + +#### Create a new gist + +**POST** /{locale}/api/create/{apiToken} +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) + +Response 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" + } +} +``` + +#### Update an existing gist + +**POST** /{locale}/api/update/{id}/{apiToken} +Params: + +* `{id}`: Gist Id (required) +* `form[content]`: String (required) + +Response 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" + } +} +``` + +#### Delete an existing gist + +**POST** /{locale}/api/delete/{id}/{apiToken} + +Response code `200`: + +```javascript +{"error":false} +``` + +Response code `400`: + +```javascript +{"message":"Invalid Gist", "error":true} +``` + Console ------- @@ -255,6 +374,11 @@ Console * **Create user**: `app/console --help user:create` * **Show stats**: `$ app/console --help stats` +### Version >= v1.7.0 + +* **List your gists**: `$ app/console --help gists` +* **Delete a gist**: `$ app/console --help delete` + Deployment ---------- From 88ce6d66dbc7687bf36545e0932f1166a663c3bc Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 02:07:41 +0200 Subject: [PATCH 21/79] Geshi removed - Prismjs added --- app/bootstrap.php.d/20-twig.php | 8 - app/bootstrap.php.d/50-git.php | 2 +- bower.json | 4 +- composer.json | 1 - src/Gist/Controller/Controller.php | 1 - src/Gist/Resources/views/View/embed.html.twig | 65 +-- .../Resources/views/View/revisions.html.twig | 41 +- src/Gist/Resources/views/View/view.html.twig | 27 +- src/Gist/Service/Gist.php | 27 +- web/app/css/geshi/dawn.css | 146 ------ web/app/css/geshi/mac-classic.css | 131 ----- web/app/css/geshi/twilight.css | 123 ----- web/app/css/geshi/vibrant-ink.css | 148 ------ web/app/css/prism-okaidia.css | 121 +++++ web/app/css/prism-solarizedlight.css | 148 ++++++ web/app/css/prism.css | 467 ++++++++++++++++++ web/app/css/themes/dark.css | 38 +- web/app/css/themes/light.css | 48 +- web/app/js/app.js | 5 +- web/app/js/prism.js | 29 ++ 20 files changed, 827 insertions(+), 753 deletions(-) delete mode 100644 web/app/css/geshi/dawn.css delete mode 100644 web/app/css/geshi/mac-classic.css delete mode 100644 web/app/css/geshi/twilight.css delete mode 100644 web/app/css/geshi/vibrant-ink.css create mode 100644 web/app/css/prism-okaidia.css create mode 100644 web/app/css/prism-solarizedlight.css create mode 100644 web/app/css/prism.css create mode 100644 web/app/js/prism.js diff --git a/app/bootstrap.php.d/20-twig.php b/app/bootstrap.php.d/20-twig.php index 54fc2ab..8da7180 100644 --- a/app/bootstrap.php.d/20-twig.php +++ b/app/bootstrap.php.d/20-twig.php @@ -12,11 +12,3 @@ $app->extend('twig', function ($twig, $app) { return $twig; }); - -$app['geshi'] = $app->share(function ($app) { - $geshi = new GeSHi(); - $geshi->enable_classes(); - $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); - - return $geshi; -}); diff --git a/app/bootstrap.php.d/50-git.php b/app/bootstrap.php.d/50-git.php index 728e2c9..7afa121 100644 --- a/app/bootstrap.php.d/50-git.php +++ b/app/bootstrap.php.d/50-git.php @@ -20,5 +20,5 @@ $app['git_working_copy'] = $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']); }); diff --git a/bower.json b/bower.json index 201d38d..464be4d 100644 --- a/bower.json +++ b/bower.json @@ -15,8 +15,8 @@ "dependencies": { "bootstrap": "3.3.4", "flag-icon-css": "0.7.1", - "SyntaxHighlighter": "3.0.83", "iframe-resizer": "2.8.6", - "jsdiff": "~2.2.2" + "jsdiff": "~2.2.2", + "Prism": "~1.8.1" } } diff --git a/composer.json b/composer.json index 2f25fac..510fa87 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,5 @@ { "require": { - "geshi/geshi": "dev-master", "silex/silex": "1.3.x-dev", "symfony/yaml": "~2.6", "symfony/twig-bridge": "~2.6", diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index e166f39..5e71381 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -91,7 +91,6 @@ abstract class Controller 'history' => $history, 'commit' => $commit, 'raw_content' => $content, - 'content' => $app['gist']->highlight($gist->getGeshiType(), $content), ); } diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index 4dd7ad1..c619e9d 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -1,15 +1,16 @@ {% extends 'base.html.twig' %} {% block css %} - {% if gist.cipher %} - - + {{ parent() }} + + + + {% if theme_settings.name == 'dark' %} + {% else %} - + {% endif %} - {{ parent() }} - {% endblock %} @@ -80,11 +69,7 @@
    - {% if gist.cipher %} -
    {{ raw_content|raw }}
    - {% else %} - {{ content|raw }} - {% endif %} +
    {{ raw_content }}
    @@ -100,37 +85,5 @@ {{ parent() }} - - {% if gist.cipher %} - - - - - {% endif %} + {% endblock %} diff --git a/src/Gist/Resources/views/View/revisions.html.twig b/src/Gist/Resources/views/View/revisions.html.twig index bcf205f..e1d2766 100644 --- a/src/Gist/Resources/views/View/revisions.html.twig +++ b/src/Gist/Resources/views/View/revisions.html.twig @@ -1,9 +1,15 @@ {% extends 'base.html.twig' %} {% block css %} - - {{ parent() }} + + + + {% if theme_settings.name == 'dark' %} + + {% else %} + + {% endif %} {% endblock %} {% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ 'gist.action.history'|trans }}{% endblock %} @@ -23,7 +29,7 @@ {{ history|length }}
  • - + @@ -76,9 +79,9 @@ {% block js %} {{ parent() }} - {% if gist.cipher %} - {{ include('View/cipherJs.html.twig') }} + + {% if gist.cipher %} {% endif %} {% endblock %} diff --git a/src/Gist/Resources/views/View/view.html.twig b/src/Gist/Resources/views/View/view.html.twig index 97db4ca..c45ed24 100644 --- a/src/Gist/Resources/views/View/view.html.twig +++ b/src/Gist/Resources/views/View/view.html.twig @@ -1,14 +1,15 @@ {% extends 'base.html.twig' %} {% block css %} - {% if gist.cipher %} - - - {% else %} - - {% endif %} - {{ parent() }} + + + + {% if theme_settings.name == 'dark' %} + + {% else %} + + {% endif %} {% endblock %} {% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ commit|slice(0, 10) }}{% endblock %} @@ -61,11 +62,7 @@
    - {% if gist.cipher %} -
    {{ raw_content|raw }}
    - {% else %} - {{ content|raw }} - {% endif %} +
    {{ raw_content }}

    @@ -82,8 +79,6 @@ {% block js %} {{ parent() }} - - {% if gist.cipher %} - {{ include('View/cipherJs.html.twig') }} - {% endif %} + + {% endblock %} diff --git a/src/Gist/Service/Gist.php b/src/Gist/Service/Gist.php index 7877164..db9b96c 100644 --- a/src/Gist/Service/Gist.php +++ b/src/Gist/Service/Gist.php @@ -32,25 +32,18 @@ class Gist */ protected $gitWorkingCopy; - /** - * @var GeSHi - */ - protected $geshi; - /** * __construct. * * @param mixed $gistPath * @param GitWrapper $gitWrapper * @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->gitWrapper = $gitWrapper; $this->gitWorkingCopy = $gitWorkingCopy; - $this->geshi = $geshi; } /** @@ -95,7 +88,7 @@ class Gist $data = array( 'commit' => trim($commits[$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()) { @@ -193,20 +186,4 @@ class Gist return count(explode("\n", $content)); } - - /** - * Highlight the content. - * - * @param string $type - * @param string $content - * - * @return string - */ - public function highlight($type, $content) - { - $this->geshi->set_source($content); - $this->geshi->set_language($type); - - return $this->geshi->parse_code(); - } } diff --git a/web/app/css/geshi/dawn.css b/web/app/css/geshi/dawn.css deleted file mode 100644 index d1e6fc4..0000000 --- a/web/app/css/geshi/dawn.css +++ /dev/null @@ -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; -} diff --git a/web/app/css/geshi/mac-classic.css b/web/app/css/geshi/mac-classic.css deleted file mode 100644 index ae152f3..0000000 --- a/web/app/css/geshi/mac-classic.css +++ /dev/null @@ -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; -} diff --git a/web/app/css/geshi/twilight.css b/web/app/css/geshi/twilight.css deleted file mode 100644 index 9e2c15c..0000000 --- a/web/app/css/geshi/twilight.css +++ /dev/null @@ -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; -} diff --git a/web/app/css/geshi/vibrant-ink.css b/web/app/css/geshi/vibrant-ink.css deleted file mode 100644 index 3c920e3..0000000 --- a/web/app/css/geshi/vibrant-ink.css +++ /dev/null @@ -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; -} diff --git a/web/app/css/prism-okaidia.css b/web/app/css/prism-okaidia.css new file mode 100644 index 0000000..3e0da35 --- /dev/null +++ b/web/app/css/prism-okaidia.css @@ -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; +} diff --git a/web/app/css/prism-solarizedlight.css b/web/app/css/prism-solarizedlight.css new file mode 100644 index 0000000..bad7703 --- /dev/null +++ b/web/app/css/prism-solarizedlight.css @@ -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; +} \ No newline at end of file diff --git a/web/app/css/prism.css b/web/app/css/prism.css new file mode 100644 index 0000000..5199180 --- /dev/null +++ b/web/app/css/prism.css @@ -0,0 +1,467 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+actionscript+c+aspnet+bash+cpp+csharp+css-extras+diff+perl+php+php-extras+python+sql+yaml&plugins=line-highlight+line-numbers+autolinker+previewer-base+previewer-color+previewer-gradient+previewer-easing+previewer-time+previewer-angle */ +/** + * 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: #a67f59; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function { + 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; + } + +pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre.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; + } +.token a { + color: inherit; +} +.prism-previewer, +.prism-previewer:before, +.prism-previewer:after { + position: absolute; + pointer-events: none; +} +.prism-previewer, +.prism-previewer:after { + left: 50%; +} +.prism-previewer { + margin-top: -48px; + width: 32px; + height: 32px; + margin-left: -16px; + + opacity: 0; + -webkit-transition: opacity .25s; + -o-transition: opacity .25s; + transition: opacity .25s; +} +.prism-previewer.flipped { + margin-top: 0; + margin-bottom: -48px; +} +.prism-previewer:before, +.prism-previewer:after { + content: ''; + position: absolute; + pointer-events: none; +} +.prism-previewer:before { + top: -5px; + right: -5px; + left: -5px; + bottom: -5px; + border-radius: 10px; + border: 5px solid #fff; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75); +} + +.prism-previewer:after { + top: 100%; + width: 0; + height: 0; + margin: 5px 0 0 -7px; + border: 7px solid transparent; + border-color: rgba(255, 0, 0, 0); + border-top-color: #fff; +} +.prism-previewer.flipped:after { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 5px; + border-top-color: rgba(255, 0, 0, 0); + border-bottom-color: #fff; +} +.prism-previewer.active { + opacity: 1; +} +.prism-previewer-color { + background-image: linear-gradient(45deg, #bbb 25%, transparent 25%, transparent 75%, #bbb 75%, #bbb), linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb); + background-size: 10px 10px; + background-position: 0 0, 5px 5px; +} +.prism-previewer-color:before { + background-color: inherit; + background-clip: padding-box; +} + +.prism-previewer-gradient { + background-image: linear-gradient(45deg, #bbb 25%, transparent 25%, transparent 75%, #bbb 75%, #bbb), linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb); + background-size: 10px 10px; + background-position: 0 0, 5px 5px; + + width: 64px; + margin-left: -32px; +} +.prism-previewer-gradient:before { + content: none; +} +.prism-previewer-gradient div { + position: absolute; + top: -5px; + left: -5px; + right: -5px; + bottom: -5px; + border-radius: 10px; + border: 5px solid #fff; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75); +} +.prism-previewer-easing { + margin-top: -76px; + margin-left: -30px; + width: 60px; + height: 60px; + background: #333; +} +.prism-previewer-easing.flipped { + margin-bottom: -116px; +} +.prism-previewer-easing svg { + width: 60px; + height: 60px; +} +.prism-previewer-easing circle { + fill: hsl(200, 10%, 20%); + stroke: white; +} +.prism-previewer-easing path { + fill: none; + stroke: white; + stroke-linecap: round; + stroke-width: 4; +} +.prism-previewer-easing line { + stroke: white; + stroke-opacity: 0.5; + stroke-width: 2; +} +@-webkit-keyframes prism-previewer-time { + 0% { + stroke-dasharray: 0, 500; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 100, 500; + stroke-dashoffset: 0; + } + 100% { + stroke-dasharray: 0, 500; + stroke-dashoffset: -100; + } +} + +@-o-keyframes prism-previewer-time { + 0% { + stroke-dasharray: 0, 500; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 100, 500; + stroke-dashoffset: 0; + } + 100% { + stroke-dasharray: 0, 500; + stroke-dashoffset: -100; + } +} + +@-moz-keyframes prism-previewer-time { + 0% { + stroke-dasharray: 0, 500; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 100, 500; + stroke-dashoffset: 0; + } + 100% { + stroke-dasharray: 0, 500; + stroke-dashoffset: -100; + } +} + +@keyframes prism-previewer-time { + 0% { + stroke-dasharray: 0, 500; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 100, 500; + stroke-dashoffset: 0; + } + 100% { + stroke-dasharray: 0, 500; + stroke-dashoffset: -100; + } +} + +.prism-previewer-time:before { + border-radius: 50%; + background: #fff; +} +.prism-previewer-time:after { + margin-top: 4px; +} +.prism-previewer-time svg { + width: 32px; + height: 32px; + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + transform: rotate(-90deg); +} +.prism-previewer-time circle { + fill: transparent; + stroke: hsl(200, 10%, 20%); + stroke-opacity: 0.9; + stroke-width: 32; + stroke-dasharray: 0, 500; + stroke-dashoffset: 0; + -webkit-animation: prism-previewer-time linear infinite 3s; + -moz-animation: prism-previewer-time linear infinite 3s; + -o-animation: prism-previewer-time linear infinite 3s; + animation: prism-previewer-time linear infinite 3s; +} +.prism-previewer-angle:before { + border-radius: 50%; + background: #fff; +} +.prism-previewer-angle:after { + margin-top: 4px; +} +.prism-previewer-angle svg { + width: 32px; + height: 32px; + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + transform: rotate(-90deg); +} +.prism-previewer-angle[data-negative] svg { + -webkit-transform: scaleX(-1) rotate(-90deg); + -moz-transform: scaleX(-1) rotate(-90deg); + -ms-transform: scaleX(-1) rotate(-90deg); + -o-transform: scaleX(-1) rotate(-90deg); + transform: scaleX(-1) rotate(-90deg); +} +.prism-previewer-angle circle { + fill: transparent; + stroke: hsl(200, 10%, 20%); + stroke-opacity: 0.9; + stroke-width: 32; + stroke-dasharray: 0, 500; +} diff --git a/web/app/css/themes/dark.css b/web/app/css/themes/dark.css index 1d4ab1c..19528c8 100644 --- a/web/app/css/themes/dark.css +++ b/web/app/css/themes/dark.css @@ -26,54 +26,24 @@ body { margin-right: 4px; } -pre { - background: #222; - border: #222; - color: #ddd; +#viewer pre, #viewer code, #revisions pre, #revisions code { + background: none !important; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word; -} - -pre ol { - padding-left: 50px !important; -} - -pre li:hover { - background: #444; + border: 0; } .panel-heading .actions { margin-top: -5px; } -div.diff { +.diff { 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 { margin-bottom: 17px; } diff --git a/web/app/css/themes/light.css b/web/app/css/themes/light.css index 372b65f..9c07b5b 100644 --- a/web/app/css/themes/light.css +++ b/web/app/css/themes/light.css @@ -16,54 +16,24 @@ margin-right: 4px; } -pre { - background: #222; - border: #222; - color: #ddd; - white-space: pre-wrap; - white-space: -moz-pre-wrap; - white-space: -pre-wrap; - white-space: -o-pre-wrap; - word-wrap: break-word; -} - -pre ol { - padding-left: 50px !important; -} - -pre li:hover { - background: #444; +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; } -div.diff { +.diff { 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 { margin-bottom: 17px; } diff --git a/web/app/js/app.js b/web/app/js/app.js index 671d102..a3624fc 100644 --- a/web/app/js/app.js +++ b/web/app/js/app.js @@ -138,7 +138,7 @@ var getKey = function() { } var viewerEvents = function() { - var $render = $('.syntaxhighlighter'); + var $render = $('#viewer code[data-cipher]'); $(document).ready(function() { var key = getKey(); @@ -163,7 +163,8 @@ var viewerEvents = function() { }); $render.text(decrypted.toString(CryptoJS.enc.Utf8)); - SyntaxHighlighter.all(); + $render.attr('class', $render.data('class')); + Prism.highlightAll(); to = ' data-key="#key=' + key + '" '; } else { diff --git a/web/app/js/prism.js b/web/app/js/prism.js new file mode 100644 index 0000000..bfb1dca --- /dev/null +++ b/web/app/js/prism.js @@ -0,0 +1,29 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+actionscript+c+aspnet+bash+cpp+csharp+css-extras+diff+perl+php+php-extras+python+sql+yaml&plugins=line-highlight+line-numbers+autolinker+previewer-base+previewer-color+previewer-gradient+previewer-easing+previewer-time+previewer-angle */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){h.lastIndex=0;var _=h.exec(w),P=1;if(!_&&m&&b!=t.length-1){if(h.lastIndex=k,_=h.exec(e),!_)break;for(var A=_.index+(d?_[1].length:0),j=_.index+_[0].length,x=b,O=k,S=t.length;S>x&&(j>O||!t[x].type&&!t[x-1].greedy);++x)O+=t[x].length,A>=O&&(++b,k=O);if(t[b]instanceof s||t[x-1].greedy)continue;P=x-b,w=e.slice(k,O),_.index-=k}if(_){d&&(p=_[1].length);var A=_.index+p,_=_[0].slice(p),j=A+_.length,N=w.slice(0,A),C=w.slice(j),E=[b,P];N&&(++b,k+=N.length,E.push(N));var I=new s(u,f?n.tokenize(_,f):_,y,_,m);if(E.push(I),C&&E.push(C),Array.prototype.splice.apply(t,E),1!=P&&n.matchGrammar(e,t,a,b,k,!0,u),l)break}else if(l)break}}}}},tokenize:function(e,t){var a=[e],r=t.rest;if(r){for(var i in r)t[i]=r[i];delete t.rest}return n.matchGrammar(e,a,t,0,0,!1),a},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var i={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}n.hooks.run("wrap",i);var o=Object.keys(i.attributes).map(function(e){return e+'="'+(i.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(o?" "+o:"")+">"+i.content+""},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,i=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),i&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\s\S]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; +Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)\s*=>))/i,alias:"function"}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript; +Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\\1|\\?(?!\1)[\s\S])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:Prism.languages.markup}}}); +Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; +Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive tag":{pattern:/<%\s*@.*%>/i,inside:{"page-directive tag":/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,rest:Prism.languages.markup.tag.inside}},"directive tag":{pattern:/<%.*%>/i,inside:{"directive tag":/<%\s*?[$=%#:]{0,2}|%>/i,rest:Prism.languages.csharp}}}),Prism.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("inside","punctuation",{"directive tag":Prism.languages.aspnet["directive tag"]},Prism.languages.aspnet.tag.inside["attr-value"]),Prism.languages.insertBefore("aspnet","comment",{"asp comment":/<%--[\s\S]*?--%>/}),Prism.languages.insertBefore("aspnet",Prism.languages.javascript?"script":"tag",{"asp script":{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.csharp||{}}}); +!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},"boolean":{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a.boolean=e.languages.bash.boolean,a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation}(Prism); +Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(true|false)\b/,operator:/[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)[a-z0-9_]+/i,lookbehind:!0}}); +Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(abstract|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/,string:[{pattern:/@("|')(\1\1|\\\1|\\?(?!\1)[\s\S])*\1/,greedy:!0},{pattern:/("|')(\\?.)*?\1/,greedy:!0}],number:/\b-?(0x[\da-f]+|\d*\.?\d+f?)\b/i}),Prism.languages.insertBefore("csharp","keyword",{"generic-method":{pattern:/[a-z0-9_]+\s*<[^>\r\n]+?>\s*(?=\()/i,alias:"function",inside:{keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}); +Prism.languages.css.selector={pattern:/[^\{\}\s][^\{\}]*(?=\s*\{)/,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:\.\w]+/,id:/#[-:\.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%\.]+/}); +Prism.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d+.*$/m],deleted:/^[-<].*$/m,inserted:/^[+>].*$/m,diff:{pattern:/^!(?!!).+$/m,alias:"important"}}; +Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:[^\\]|\\.)*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?((::)*'?(?!\d)[\w$]+)+(::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(\.\d+)*|\d+(\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b-?(0x[\dA-Fa-f](_?[\dA-Fa-f])*|0b[01](_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; +Prism.languages.php=Prism.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),Prism.languages.insertBefore("php","class-name",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),Prism.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$\w+\b/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),Prism.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}}),Prism.languages.markup&&(Prism.hooks.add("before-highlight",function(e){"php"===e.language&&/(?:<\?php|<\?)/gi.test(e.code)&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi,function(a){for(var n=e.tokenStack.length;-1!==e.backupCode.indexOf("___PHP"+n+"___");)++n;return e.tokenStack[n]=a,"___PHP"+n+"___"}),e.grammar=Prism.languages.markup)}),Prism.hooks.add("before-insert",function(e){"php"===e.language&&e.backupCode&&(e.code=e.backupCode,delete e.backupCode)}),Prism.hooks.add("after-highlight",function(e){if("php"===e.language&&e.tokenStack){e.grammar=Prism.languages.php;for(var a=0,n=Object.keys(e.tokenStack);a'+Prism.highlight(r,e.grammar,"php").replace(/\$/g,"$$$$")+"")}e.element.innerHTML=e.highlightedCode}})); +Prism.languages.insertBefore("php","variable",{"this":/\$this\b/,global:/\$(?:_(?:SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE)|GLOBALS|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/(static|self|parent)/,punctuation:/(::|\\)/}}}); +Prism.languages.python={"triple-quoted-string":{pattern:/"""[\s\S]+?"""|'''[\s\S]+?'''/,alias:"string"},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/("|')(?:\\\\|\\?[^\\\r\n])*?\1/,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,"boolean":/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},string:{pattern:/(^|[^@\\])("|')(?:\\?[\s\S])*?\2/,greedy:!0,lookbehind:!0},variable:/@[\w.$]+|@("|'|`)(?:\\?[\s\S])+?\1/,"function":/\b(?:COUNT|SUM|AVG|MIN|MAX|FIRST|LAST|UCASE|LCASE|MID|LEN|ROUND|NOW|FORMAT)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR VARYING|CHARACTER (?:SET|VARYING)|CHARSET|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|DATA(?:BASES?)?|DATE(?:TIME)?|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITER(?:S)?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE(?: PRECISION)?|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE(?:D BY)?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEYS?|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL(?: CHAR VARYING| CHARACTER(?: VARYING)?| VARCHAR)?|NATURAL|NCHAR(?: VARCHAR)?|NEXT|NO(?: SQL|CHECK|CYCLE)?|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READ(?:S SQL DATA|TEXT)?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START(?:ING BY)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED BY|TEXT(?:SIZE)?|THEN|TIMESTAMP|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNPIVOT|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?)\b/i,"boolean":/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b-?(?:0x)?\d*\.?[\da-f]+\b/,operator:/[-+*\/=%^~]|&&?|\|?\||!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; +Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\3[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(\d{4}-\d\d?-\d\d?([tT]|[ \t]+)\d\d?:\d{2}:\d{2}(\.\d*)?[ \t]*(Z|[-+]\d\d?(:\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(:\d{2}(\.\d*)?)?)(?=[ \t]*($|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')(?=[ \t]*($|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)[+\-]?(0x[\da-f]+|0o[0-7]+|(\d+\.?\d*|\.?\d+)(e[\+\-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}; +!function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){for(var o,a=n.replace(/\s+/g,"").split(","),l=+e.getAttribute("data-line-offset")||0,d=r()?parseInt:parseFloat,c=d(getComputedStyle(e).lineHeight),s=0;o=a[s++];){o=o.split("-");var u=+o[0],m=+o[1]||u,h=document.createElement("div");h.textContent=Array(m-u+2).join(" \n"),h.setAttribute("aria-hidden","true"),h.className=(i||"")+" line-highlight",t(e,"line-numbers")||(h.setAttribute("data-start",u),m>u&&h.setAttribute("data-end",m)),h.style.top=(u-l-1)*c+"px",t(e,"line-numbers")?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML=" 
     ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function(e){var t=e.element.parentNode,r=t&&t.getAttribute("data-line");t&&r&&/pre/i.test(t.nodeName)&&(clearTimeout(o),n(t,r),o=setTimeout(i,1))}),window.addEventListener("hashchange",i)}}(); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=function(e){var t=n(e),r=t["white-space"];if("pre-wrap"===r||"pre-line"===r){var s=e.querySelector("code"),l=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),i=e.textContent.split("\n");a||(a=document.createElement("span"),a.className="line-numbers-sizer",s.appendChild(a)),a.style.display="block",i.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;l.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},n=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),t)}),Prism.hooks.add("complete",function(e){if(e.code){var n=e.element.parentNode,r=/\s*\bline-numbers\b\s*/;if(n&&/pre/i.test(n.nodeName)&&(r.test(n.className)||r.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){r.test(e.element.className)&&(e.element.className=e.element.className.replace(r," ")),r.test(n.className)||(n.className+=" line-numbers");var s,l=e.code.match(/\n(?!$)/g),a=l?l.length+1:1,i=new Array(a+1);i=i.join(""),s=document.createElement("span"),s.setAttribute("aria-hidden","true"),s.className="line-numbers-rows",s.innerHTML=i,n.hasAttribute("data-start")&&(n.style.counterReset="linenumber "+(parseInt(n.getAttribute("data-start"),10)-1)),e.element.appendChild(s),t(n)}}})}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:#=?&]+/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(a){a&&!a["url-link"]&&(Prism.languages.DFS(a,function(a,r,l){t.indexOf(l)>-1&&"Array"!==Prism.util.type(r)&&(r.pattern||(r=this[a]={pattern:r}),r.inside=r.inside||{},"comment"==l&&(r.inside["md-link"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},r):r.inside["url-link"]=i,r.inside["email-link"]=n)}),a["url-link"]=i,a["email-link"]=n)}},Prism.hooks.add("before-highlight",function(i){Prism.plugins.autolinker.processGrammar(i.grammar)}),Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var t=i.content.match(e);n=t[2],i.content=t[1]}i.attributes.href=n}try{i.content=decodeURIComponent(i.content)}catch(a){}})}}(); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&Function.prototype.bind){var t=function(t){var e=0,s=0,i=t;if(i.parentNode){do e+=i.offsetLeft,s+=i.offsetTop;while((i=i.offsetParent)&&i.nodeType<9);i=t;do e-=i.scrollLeft,s-=i.scrollTop;while((i=i.parentNode)&&!/body/i.test(i.nodeName))}return{top:s,right:innerWidth-e-t.offsetWidth,bottom:innerHeight-s-t.offsetHeight,left:e}},e=/(?:^|\s)token(?=$|\s)/,s=/(?:^|\s)active(?=$|\s)/g,i=/(?:^|\s)flipped(?=$|\s)/g,o=function(t,e,s,i){this._elt=null,this._type=t,this._clsRegexp=RegExp("(?:^|\\s)"+t+"(?=$|\\s)"),this._token=null,this.updater=e,this._mouseout=this.mouseout.bind(this),this.initializer=i;var n=this;s||(s=["*"]),"Array"!==Prism.util.type(s)&&(s=[s]),s.forEach(function(t){"string"!=typeof t&&(t=t.lang),o.byLanguages[t]||(o.byLanguages[t]=[]),o.byLanguages[t].indexOf(n)<0&&o.byLanguages[t].push(n)}),o.byType[t]=this};o.prototype.init=function(){this._elt||(this._elt=document.createElement("div"),this._elt.className="prism-previewer prism-previewer-"+this._type,document.body.appendChild(this._elt),this.initializer&&this.initializer())},o.prototype.check=function(t){do if(e.test(t.className)&&this._clsRegexp.test(t.className))break;while(t=t.parentNode);t&&t!==this._token&&(this._token=t,this.show())},o.prototype.mouseout=function(){this._token.removeEventListener("mouseout",this._mouseout,!1),this._token=null,this.hide()},o.prototype.show=function(){if(this._elt||this.init(),this._token)if(this.updater.call(this._elt,this._token.textContent)){this._token.addEventListener("mouseout",this._mouseout,!1);var e=t(this._token);this._elt.className+=" active",e.top-this._elt.offsetHeight>0?(this._elt.className=this._elt.className.replace(i,""),this._elt.style.top=e.top+"px",this._elt.style.bottom=""):(this._elt.className+=" flipped",this._elt.style.bottom=e.bottom+"px",this._elt.style.top=""),this._elt.style.left=e.left+Math.min(200,this._token.offsetWidth/2)+"px"}else this.hide()},o.prototype.hide=function(){this._elt.className=this._elt.className.replace(s,"")},o.byLanguages={},o.byType={},o.initEvents=function(t,e){var s=[];o.byLanguages[e]&&(s=s.concat(o.byLanguages[e])),o.byLanguages["*"]&&(s=s.concat(o.byLanguages["*"])),t.addEventListener("mouseover",function(t){var e=t.target;s.forEach(function(t){t.check(e)})},!1)},Prism.plugins.Previewer=o,Prism.hooks.add("after-highlight",function(t){(o.byLanguages["*"]||o.byLanguages[t.language])&&o.initEvents(t.element,t.language)})}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var e={css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(a){if(a.language&&e[a.language]&&!e[a.language].initialized){var i=e[a.language];"Array"!==Prism.util.type(i)&&(i=[i]),i.forEach(function(i){var r,l,n,s;i===!0?(r="important",l=a.language,i=a.language):(r=i.before||"important",l=i.inside||i.lang,n=i.root||Prism.languages,s=i.skip,i=a.language),!s&&Prism.languages[i]&&(Prism.languages.insertBefore(l,r,{color:/\B#(?:[0-9a-f]{3}){1,2}\b|\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B|\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGray|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGray|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGray|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gray|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGray|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGray|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGray|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i},n),a.grammar=Prism.languages[i],e[a.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("color",function(e){return this.style.backgroundColor="",this.style.backgroundColor=e,!!this.style.backgroundColor})}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var e={css:!0,less:!0,sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(i){if(i.language&&e[i.language]&&!e[i.language].initialized){var t=e[i.language];"Array"!==Prism.util.type(t)&&(t=[t]),t.forEach(function(t){var r,s,a,n;t===!0?(r=Prism.plugins.Previewer&&Prism.plugins.Previewer.byType.color?"color":"important",s=i.language,t=i.language):(r=t.before||"important",s=t.inside||t.lang,a=t.root||Prism.languages,n=t.skip,t=i.language),!n&&Prism.languages[t]&&(Prism.languages.insertBefore(s,r,{gradient:{pattern:/(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:rgb|hsl)a?\(.+?\)|[^\)])+\)/gi,inside:{"function":/[\w-]+(?=\()/,punctuation:/[(),]/}}},a),i.grammar=Prism.languages[t],e[i.language]={initialized:!0})})}});var i={},t=function(e,i,t){var r="180deg";return/^(?:-?\d*\.?\d+(?:deg|rad)|to\b|top|right|bottom|left)/.test(t[0])&&(r=t.shift(),r.indexOf("to ")<0&&(r.indexOf("top")>=0?r=r.indexOf("left")>=0?"to bottom right":r.indexOf("right")>=0?"to bottom left":"to bottom":r.indexOf("bottom")>=0?r=r.indexOf("left")>=0?"to top right":r.indexOf("right")>=0?"to top left":"to top":r.indexOf("left")>=0?r="to right":r.indexOf("right")>=0?r="to left":e&&(r.indexOf("deg")>=0?r=90-parseFloat(r)+"deg":r.indexOf("rad")>=0&&(r=Math.PI/2-parseFloat(r)+"rad")))),i+"("+r+","+t.join(",")+")"},r=function(e,i,t){if(t[0].indexOf("at")<0){var r="center",s="ellipse",a="farthest-corner";if(/\bcenter|top|right|bottom|left\b|^\d+/.test(t[0])&&(r=t.shift().replace(/\s*-?\d+(?:rad|deg)\s*/,"")),/\bcircle|ellipse|closest|farthest|contain|cover\b/.test(t[0])){var n=t.shift().split(/\s+/);!n[0]||"circle"!==n[0]&&"ellipse"!==n[0]||(s=n.shift()),n[0]&&(a=n.shift()),"cover"===a?a="farthest-corner":"contain"===a&&(a="clothest-side")}return i+"("+s+" "+a+" at "+r+","+t.join(",")+")"}return i+"("+t.join(",")+")"},s=function(e){if(i[e])return i[e];var s=e.match(/^(\b|\B-[a-z]{1,10}-)((?:repeating-)?(?:linear|radial)-gradient)/),a=s&&s[1],n=s&&s[2],l=e.replace(/^(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\(|\)$/g,"").split(/\s*,\s*/);return i[e]=n.indexOf("linear")>=0?t(a,n,l):n.indexOf("radial")>=0?r(a,n,l):n+"("+l.join(",")+")"};Prism.plugins.Previewer&&new Prism.plugins.Previewer("gradient",function(e){return this.firstChild.style.backgroundImage="",this.firstChild.style.backgroundImage=s(e),!!this.firstChild.style.backgroundImage},"*",function(){this._elt.innerHTML="

    "})}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var e={css:!0,less:!0,sass:[{lang:"sass",inside:"inside",before:"punctuation",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(r){if(r.language&&e[r.language]&&!e[r.language].initialized){var s=e[r.language];"Array"!==Prism.util.type(s)&&(s=[s]),s.forEach(function(s){var i,a,n,t;s===!0?(i="important",a=r.language,s=r.language):(i=s.before||"important",a=s.inside||s.lang,n=s.root||Prism.languages,t=s.skip,s=r.language),!t&&Prism.languages[s]&&(Prism.languages.insertBefore(a,i,{easing:/\bcubic-bezier\((?:-?\d*\.?\d+,\s*){3}-?\d*\.?\d+\)\B|\b(?:linear|ease(?:-in)?(?:-out)?)(?=\s|[;}]|$)/i},n),r.grammar=Prism.languages[s],e[r.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("easing",function(e){e={linear:"0,0,1,1",ease:".25,.1,.25,1","ease-in":".42,0,1,1","ease-out":"0,0,.58,1","ease-in-out":".42,0,.58,1"}[e]||e;var r=e.match(/-?\d*\.?\d+/g);if(4===r.length){r=r.map(function(e,r){return 100*(r%2?1-e:e)}),this.querySelector("path").setAttribute("d","M0,100 C"+r[0]+","+r[1]+", "+r[2]+","+r[3]+", 100,0");var s=this.querySelectorAll("line");return s[0].setAttribute("x2",r[0]),s[0].setAttribute("y2",r[1]),s[1].setAttribute("x2",r[2]),s[1].setAttribute("y2",r[3]),!0}return!1},"*",function(){this._elt.innerHTML=''})}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var s={css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(e){if(e.language&&s[e.language]&&!s[e.language].initialized){var a=s[e.language];"Array"!==Prism.util.type(a)&&(a=[a]),a.forEach(function(a){var i,r,n,l;a===!0?(i="important",r=e.language,a=e.language):(i=a.before||"important",r=a.inside||a.lang,n=a.root||Prism.languages,l=a.skip,a=e.language),!l&&Prism.languages[a]&&(Prism.languages.insertBefore(r,i,{time:/(?:\b|\B-|(?=\B\.))\d*\.?\d+m?s\b/i},n),e.grammar=Prism.languages[a],s[e.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("time",function(s){var e=parseFloat(s),a=s.match(/[a-z]+$/i);return e&&a?(a=a[0],this.querySelector("circle").style.animationDuration=2*e+a,!0):!1},"*",function(){this._elt.innerHTML=''})}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var a={css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(s){if(s.language&&a[s.language]&&!a[s.language].initialized){var e=a[s.language];"Array"!==Prism.util.type(e)&&(e=[e]),e.forEach(function(e){var i,r,n,g;e===!0?(i="important",r=s.language,e=s.language):(i=e.before||"important",r=e.inside||e.lang,n=e.root||Prism.languages,g=e.skip,e=s.language),!g&&Prism.languages[e]&&(Prism.languages.insertBefore(r,i,{angle:/(?:\b|\B-|(?=\B\.))\d*\.?\d+(?:deg|g?rad|turn)\b/i},n),s.grammar=Prism.languages[e],a[s.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("angle",function(a){var s,e,i=parseFloat(a),r=a.match(/[a-z]+$/i);if(!i||!r)return!1;switch(r=r[0]){case"deg":s=360;break;case"grad":s=400;break;case"rad":s=2*Math.PI;break;case"turn":s=1}return e=100*i/s,e%=100,this[(0>i?"set":"remove")+"Attribute"]("data-negative",""),this.querySelector("circle").style.strokeDasharray=Math.abs(e)+",500",!0},"*",function(){this._elt.innerHTML=''})}}(); From 21a85c0db4a69bebeb45dd452fac1f7bacd49d06 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 02:18:59 +0200 Subject: [PATCH 22/79] Embed view css --- src/Gist/Resources/views/View/embed.html.twig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index c619e9d..cc35adc 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -16,10 +16,6 @@ padding: 0; } - #viewer { - background: #222; - } - .panel-body { padding: 0; } From 1a79e4520f0db9423fb414c5534fd5004637d51d Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 02:58:10 +0200 Subject: [PATCH 23/79] Embed block moved --- app/locales/cn.yml | 2 +- app/locales/de.yml | 2 +- app/locales/en.yml | 2 +- app/locales/es.yml | 2 +- app/locales/fr.yml | 2 +- src/Gist/Resources/views/View/embed.html.twig | 4 ---- src/Gist/Resources/views/View/view.html.twig | 18 +++++++++++++----- web/app/css/themes/dark.css | 2 +- web/app/js/app.js | 6 +++--- 9 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/locales/cn.yml b/app/locales/cn.yml index adfe2d8..9af2b92 100644 --- a/app/locales/cn.yml +++ b/app/locales/cn.yml @@ -37,7 +37,7 @@ gist: raw: '源文件' download: '下载' clone: '克隆' - embed: '引用:' + embed: '引用' add: '新建' date: diff --git a/app/locales/de.yml b/app/locales/de.yml index c91934d..28a0314 100644 --- a/app/locales/de.yml +++ b/app/locales/de.yml @@ -37,7 +37,7 @@ gist: raw: 'RAW' download: 'Herunterladen' clone: 'Klonen' - embed: 'Einfügen:' + embed: 'Einfügen' add: 'Hinzufügen' date: diff --git a/app/locales/en.yml b/app/locales/en.yml index ff80822..dd99aba 100644 --- a/app/locales/en.yml +++ b/app/locales/en.yml @@ -38,7 +38,7 @@ gist: raw: 'RAW' download: 'Download' clone: 'Clone' - embed: 'Embed:' + embed: 'Embed' add: 'New' date: diff --git a/app/locales/es.yml b/app/locales/es.yml index 2d8176b..679d0f1 100644 --- a/app/locales/es.yml +++ b/app/locales/es.yml @@ -37,7 +37,7 @@ gist: raw: 'RAW' download: 'Descargar' clone: 'Clonar' - embed: 'Insertar : ' + embed: 'Insertar' add: 'Añadir' date: diff --git a/app/locales/fr.yml b/app/locales/fr.yml index 8741cf5..68759cd 100644 --- a/app/locales/fr.yml +++ b/app/locales/fr.yml @@ -37,7 +37,7 @@ gist: raw: 'RAW' download: 'Télécharger' clone: 'Clôner' - embed: 'Insérer : ' + embed: 'Insérer' add: 'Ajouter' date: diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index cc35adc..0e456a3 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -12,10 +12,6 @@ {% endif %} {% endblock %} From d56c33c29f180016341aa8a7cd7e385fb3c5b07c Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 12:40:52 +0200 Subject: [PATCH 26/79] Fix highlighting for ASP and ActionScript --- src/Gist/Model/Gist.php | 6 ++++-- src/Gist/Resources/views/View/embed.html.twig | 2 +- src/Gist/Resources/views/View/view.html.twig | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Gist/Model/Gist.php b/src/Gist/Model/Gist.php index 86efe42..54142bc 100644 --- a/src/Gist/Model/Gist.php +++ b/src/Gist/Model/Gist.php @@ -45,14 +45,16 @@ class Gist extends BaseGist } /** - * Returns the type for Geshi. + * Returns the type for highlighting. * * @return string */ - public function getGeshiType() + public function getHighlightType() { $data = array( 'html' => 'xml', + 'asp' => 'aspnet', + 'actionscript3' => 'actionscript', ); return str_replace(array_keys($data), array_values($data), $this->getType()); diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index 155cc2e..12c7f1b 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -65,7 +65,7 @@
    -
    {{ raw_content }}
    +
    {{ raw_content }}
    diff --git a/src/Gist/Resources/views/View/view.html.twig b/src/Gist/Resources/views/View/view.html.twig index 58ba304..7891faf 100644 --- a/src/Gist/Resources/views/View/view.html.twig +++ b/src/Gist/Resources/views/View/view.html.twig @@ -62,7 +62,7 @@
    -
    {{ raw_content }}
    +
    {{ raw_content }}
    From db8b512670c522d653f8941b510d122562e6a99a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 13:18:06 +0200 Subject: [PATCH 27/79] Mobile view optimised --- src/Gist/Resources/views/View/embed.html.twig | 80 +++++++++++++----- src/Gist/Resources/views/View/view.html.twig | 81 ++++++++++++++----- 2 files changed, 118 insertions(+), 43 deletions(-) diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index 12c7f1b..c69eda7 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -35,31 +35,67 @@
    -
    - - - {{ commit|slice(0, 10) }} - - + - - {{ gist.title ? gist.title : 'gist.untitled'|trans }}
    diff --git a/src/Gist/Resources/views/View/view.html.twig b/src/Gist/Resources/views/View/view.html.twig index 7891faf..b722578 100644 --- a/src/Gist/Resources/views/View/view.html.twig +++ b/src/Gist/Resources/views/View/view.html.twig @@ -33,30 +33,69 @@
    -
    - - {{ commit|slice(0, 10) }} - +
    +
    + {{ gist.title ? gist.title : 'gist.untitled'|trans }} +
    +
    - - {{ gist.title ? gist.title : 'gist.untitled'|trans }} -
    From 3a78e500dfbca3437f5f9ddb13a7696841a7a2b2 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 13:19:45 +0200 Subject: [PATCH 28/79] Mobile view optimised --- src/Gist/Resources/views/View/embed.html.twig | 2 +- src/Gist/Resources/views/View/view.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index c69eda7..44ff7df 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -60,7 +60,7 @@
  • - + {{ 'gist.action.download'|trans }}
  • diff --git a/src/Gist/Resources/views/View/view.html.twig b/src/Gist/Resources/views/View/view.html.twig index b722578..33dbc7e 100644 --- a/src/Gist/Resources/views/View/view.html.twig +++ b/src/Gist/Resources/views/View/view.html.twig @@ -58,7 +58,7 @@
  • - + {{ 'gist.action.download'|trans }}
  • From ebc0ea2bf85070305c9681a8e7510ab501be0128 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 15 Oct 2017 13:28:49 +0200 Subject: [PATCH 29/79] Fix empty file validation --- src/Gist/Controller/EditController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Gist/Controller/EditController.php b/src/Gist/Controller/EditController.php index d9a4ceb..1767dce 100644 --- a/src/Gist/Controller/EditController.php +++ b/src/Gist/Controller/EditController.php @@ -43,7 +43,9 @@ class EditController extends Controller if (empty($form->getData()['content']) && $form->get('file')->getData()) { $data['content'] = file_get_contents($form->get('file')->getData()->getPathName()); unset($data['file']); - } elseif (empty($form->getData()['content'])) { + } + + if (empty($data['content'])) { $form->get('content')->addError(new FormError($app['translator']->trans('form.error.not_blank'))); } From b74960ecd342154de60881a0f00eaa6816012fdb Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 16 Oct 2017 13:32:01 +0200 Subject: [PATCH 30/79] Fix download issue --- src/Gist/Controller/ViewController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index fd9f262..44aeedc 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -131,7 +131,7 @@ class ViewController extends Controller 200, array( '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', ) ); From d73e4df326c500b6a7b10324651d6eeae8ee55d3 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 28 Mar 2018 12:06:25 +0200 Subject: [PATCH 31/79] Fix issue #12: make error in Debian 9 Stretch --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 599de5e..7dd29cc 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,6 @@ update: @echo "-----------------------------------" @echo - sh -c 'test -d app && $(GIT) add app && $(GIT) commit -m "Configuration"' $(GIT) pull origin master ${MKDIR} -p data/git $(COMPOSER) update From a0e305117c9cea857e9fa775477f12a776c53aba Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 12 Apr 2018 09:19:12 +0200 Subject: [PATCH 32/79] Polish langage added --- README.md | 1 + app/bootstrap.php.d/30-trans.php | 2 +- src/Gist/Resources/views/base.html.twig | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9e1493..8a0420b 100644 --- a/README.md +++ b/README.md @@ -416,3 +416,4 @@ Contributors * Marjorie Da Silva * Mélanie Chanat * Showfom +* Tavin diff --git a/app/bootstrap.php.d/30-trans.php b/app/bootstrap.php.d/30-trans.php index 9ec8a36..d65aa5d 100644 --- a/app/bootstrap.php.d/30-trans.php +++ b/app/bootstrap.php.d/30-trans.php @@ -11,7 +11,7 @@ use Symfony\Component\HttpFoundation\Cookie; $app->register(new TranslationServiceProvider(), array( 'locale' => 'en', 'locale_fallback' => 'en', - 'locales' => array('en', 'fr', 'es', 'de', 'cn'), + 'locales' => array('en', 'fr', 'es', 'de', 'cn', 'pl'), )); $app['translator'] = $app->extend('translator', function ($translator, $app) { diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index aedcedb..6bebf64 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -81,7 +81,7 @@ {% block langs %}

    Napędzane przez GIST, to jest open source :) - API

    ' + +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' + perl: 'PERL' + c: 'C/C++' + asp: 'ASP' + python: 'PYTHON' + bash: 'BASH' + actionscript3: 'ACTION SCRIPT' + text: 'TEXT' From e74a87a131c41ae1d41ef922cffe396aafa0e13c Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 4 May 2018 18:52:37 +0200 Subject: [PATCH 34/79] composer.json updated --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 510fa87..cc07da5 100644 --- a/composer.json +++ b/composer.json @@ -1,4 +1,7 @@ { + "name": "deblan/gist", + "license": "GPL-3.0-only", + "type": "project", "require": { "silex/silex": "1.3.x-dev", "symfony/yaml": "~2.6", From 2584014d78c88a908a64f111de06d436ae9b2abd Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 25 Jun 2018 16:24:23 +0200 Subject: [PATCH 35/79] Test of post install script --- composer.json | 11 +++++++++++ propel-dist.yaml | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index cc07da5..14cd8e1 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,17 @@ "guzzlehttp/guzzle": "~6.0", "symfony/security": "^2.7" }, + "scripts": { + "gist-scripts": [ + "Gist\\Composer\\PostInstallHandler::execute" + ], + "post-install-cmd": [ + "@gist-scripts" + ], + "post-update-cmd": [ + "@gist-scripts" + ] + }, "autoload": { "psr-0": { "": "src/" diff --git a/propel-dist.yaml b/propel-dist.yaml index dd6f836..e88311b 100644 --- a/propel-dist.yaml +++ b/propel-dist.yaml @@ -4,9 +4,9 @@ propel: default: adapter: mysql classname: Propel\Runtime\Connection\ConnectionWrapper - dsn: "mysql:host=localhost;dbname=gist" - user: root - password: root + dsn: "mysql:host=DATABASE_HOST;dbname=DATABASE_NAME" + user: "DATABASE_USER" + password: "DATABASE_PASSWORD" settings: charset: utf8 queries: From acf48c4a754a0131faef2502da18fd01997615dd Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 09:37:19 +0200 Subject: [PATCH 36/79] Documentation --- README.md | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 8a0420b..b854ff3 100644 --- a/README.md +++ b/README.md @@ -40,41 +40,41 @@ Requirements Git can maybe be downloaded from your system's repositories. - $ git config --global user.email "you@example.com" - $ git config --global user.name "Your Name" + $ git config --global user.email "you@example.com" + $ git config --global user.name "Your Name" ### Composer Composer can maybe be downloaded from your system's repositories. Else, follow the next instructions: - # With cURL - $ curl -sS https://getcomposer.org/installer | php + # With cURL + $ curl -sS https://getcomposer.org/installer | php - # With Wget - $ wget -O - -q https://getcomposer.org/installer | php + # With Wget + $ wget -O - -q https://getcomposer.org/installer | php - $ chmod +x composer.phar + $ chmod +x composer.phar - # For a local installation and if the envvar PATH contains "$HOME/bin/" - $ mv composer.phar ~/bin/composer + # 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 + # For a global installation + $ sudo mv composer.phar /usr/local/bin/composer ### Bower - $ sudo apt-get install npm - $ sudo npm install -g 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 - $ cp propel-dist.yaml propel.yaml + $ cd /path/to/www/ + $ git clone https://gitnet.fr/deblan/gist + $ cd gist + $ make + $ cp propel-dist.yaml propel.yaml Edit `propel.yaml`. **Use spaces instead of tabulations**. @@ -120,12 +120,12 @@ See the [configuration section](#configuration) for more information about confi The web server must have permission to write into `data`. - $ sudo chown -R www-data:www-data 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 + $ sudo a2enmod rewrite + $ sudo service apache2 restart `app_dev.php` is the development router. Access is granted for an IP range defined in the same file. @@ -134,8 +134,8 @@ Upgrade If your version is less than v1.4.2, run: `test -d app && git add app && git commit -m "Configuration"`. - $ make update - $ make propel + $ make update + $ make propel If you upgrade to v1.4.1 or more: `app/console migrate:to:v1.4.1`. @@ -282,7 +282,7 @@ Response example: "file": "55abcfa7771e0", "createdAt": "2015-07-19T16:26:15Z", "updatedAt": "2015-07-19T16:30:15Z" - "url": "https:\/\/gist.deblan.org\/en\/view\/55abcfa7771e0\/abcgi72967dd95e3461490dcaa310d728d6adef", + "url": "https:\/\/gist.deblan.org\/en\/view\/55abcfa7771e0\/abcgi72967dd95e3461490dcaa310d728d6adef", }, { "id": 67, @@ -292,9 +292,9 @@ Response example: "file": "xyzbcfa7771e0", "createdAt": "2015-08-19T16:26:15Z", "updatedAt": "2015-08-19T16:30:15Z" - "url": "https:\/\/gist.deblan.org\/en\/view\/5byzbcfa7771e0\/def72967dd95e346koq0dcaa310d728d6artu", + "url": "https:\/\/gist.deblan.org\/en\/view\/5byzbcfa7771e0\/def72967dd95e346koq0dcaa310d728d6artu", }, - ... + ... ] ``` @@ -386,21 +386,21 @@ 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 + $ 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 + $ 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 + # global installation + $ mage deploy to:prod - # local installation - $ ./vendor/andres-montanez/magallanes/bin/mage deploy to:prod + # local installation + $ ./vendor/andres-montanez/magallanes/bin/mage deploy to:prod Contributors ------------ From 31ffaced481b3d46587e20003ef39978d6a3a027 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 09:38:51 +0200 Subject: [PATCH 37/79] Fix issue with API: the client requested 'list' instead of 'update' for updating gist and the update controller found bad gist --- src/Gist/Api/Client.php | 2 +- src/Gist/Controller/ApiController.php | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Gist/Api/Client.php b/src/Gist/Api/Client.php index 82ed6cd..ca17817 100644 --- a/src/Gist/Api/Client.php +++ b/src/Gist/Api/Client.php @@ -88,7 +88,7 @@ class Client extends BaseClient public function update($gist, $content) { $response = $this->post( - str_replace('{gist}', $gist, $this->mergeApiKey(self::LIST)), + str_replace('{gist}', $gist, $this->mergeApiKey(self::UPDATE)), array( 'form_params' => array( 'form' => array( diff --git a/src/Gist/Controller/ApiController.php b/src/Gist/Controller/ApiController.php index 89e18e1..283a616 100644 --- a/src/Gist/Controller/ApiController.php +++ b/src/Gist/Controller/ApiController.php @@ -158,12 +158,16 @@ class ApiController extends Controller return $this->invalidMethodResponse('POST method is required.'); } - $gist = GistQuery::create() - ->filterByCipher(false) - ->filterById((int) $gist) - ->_or() - ->filterByFile($gist) - ->findOne(); + $query = GistQuery::create() + ->filterByCipher(false); + + if (ctype_digit($gist)) { + $query->filterById((int) $gist); + } else { + $query->filterByFile($gist); + } + + $gist = $query->findOne(); if (!$gist) { return $this->invalidRequestResponse('Invalid Gist'); From 851dbd282b6cfa819c8314146a6eed40e7337fb1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 11:29:15 +0200 Subject: [PATCH 38/79] Composer installation handler: database configuration templates --- app/config/propel.yaml.dist-mysql | 32 ++++++++++++++++++++++++++++++ app/config/propel.yaml.dist-sqlite | 32 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 app/config/propel.yaml.dist-mysql create mode 100644 app/config/propel.yaml.dist-sqlite diff --git a/app/config/propel.yaml.dist-mysql b/app/config/propel.yaml.dist-mysql new file mode 100644 index 0000000..fa13d75 --- /dev/null +++ b/app/config/propel.yaml.dist-mysql @@ -0,0 +1,32 @@ +propel: + database: + connections: + default: + adapter: mysql + classname: Propel\Runtime\Connection\ConnectionWrapper + dsn: "mysql:host=DATABASE_HOST;dbname=DATABASE_NAME" + user: "DATABASE_USERNAME" + password: "DATABASE_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" + + 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 diff --git a/app/config/propel.yaml.dist-sqlite b/app/config/propel.yaml.dist-sqlite new file mode 100644 index 0000000..8580a0b --- /dev/null +++ b/app/config/propel.yaml.dist-sqlite @@ -0,0 +1,32 @@ +propel: + database: + connections: + default: + adapter: mysql + classname: Propel\Runtime\Connection\ConnectionWrapper + dsn: "sqlite:DATABASE_PATH" + user: ~ + 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" + + 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 From 41d1770dc28ff8051ab19500edcbc204eb9284ee Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 11:29:38 +0200 Subject: [PATCH 39/79] Composer installation handler --- src/Gist/Composer/PostInstallHandler.php | 211 +++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/Gist/Composer/PostInstallHandler.php diff --git a/src/Gist/Composer/PostInstallHandler.php b/src/Gist/Composer/PostInstallHandler.php new file mode 100644 index 0000000..81650a0 --- /dev/null +++ b/src/Gist/Composer/PostInstallHandler.php @@ -0,0 +1,211 @@ + + */ +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().'/app/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; + } +} From b25809bda68a99b931221d164a8b00214c241a28 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 11:30:35 +0200 Subject: [PATCH 40/79] propel configration file ignored --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 28eb5fc..0d685da 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /.mage/logs/*.log /composer.lock /vendor/ -/propel.yml +/propel.yaml /src/Gist/Model/Base/ /src/Gist/Model/Map/ /web/components/ From ff4a592203ec120974de20b2aea4cd1c3f392bbb Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 11:47:37 +0200 Subject: [PATCH 41/79] Mage removed from the project and the documentation --- .mage/config/environment/.gitignore | 0 .mage/config/environment/prod.yml.dist | 28 -------------------------- .mage/config/general.yml | 7 ------- .mage/logs/.gitignore | 2 -- .mage/tasks/.gitignore | 0 5 files changed, 37 deletions(-) delete mode 100644 .mage/config/environment/.gitignore delete mode 100644 .mage/config/environment/prod.yml.dist delete mode 100644 .mage/config/general.yml delete mode 100644 .mage/logs/.gitignore delete mode 100644 .mage/tasks/.gitignore diff --git a/.mage/config/environment/.gitignore b/.mage/config/environment/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/.mage/config/environment/prod.yml.dist b/.mage/config/environment/prod.yml.dist deleted file mode 100644 index a5bcb3b..0000000 --- a/.mage/config/environment/prod.yml.dist +++ /dev/null @@ -1,28 +0,0 @@ -# prod -# Rename this file to "prod.yml" -deployment: - user: gist - from: ./ - to: /var/www/gist/ - excludes: - - "*.svn" - - "*.git" - - "*.swp" - - "app/config/config.yml" - - "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 diff --git a/.mage/config/general.yml b/.mage/config/general.yml deleted file mode 100644 index cff23fa..0000000 --- a/.mage/config/general.yml +++ /dev/null @@ -1,7 +0,0 @@ -# global settings -name: Gist -email: -notifications: false -logging: true -maxlogs: 30 -ssh_needs_tty: false diff --git a/.mage/logs/.gitignore b/.mage/logs/.gitignore deleted file mode 100644 index c96a04f..0000000 --- a/.mage/logs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/.mage/tasks/.gitignore b/.mage/tasks/.gitignore deleted file mode 100644 index e69de29..0000000 From 301fca186d52041f2aed52b3a9083fa82e1db133 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 11:47:56 +0200 Subject: [PATCH 42/79] Propel configuration template replaced --- propel-dist.yaml | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 propel-dist.yaml diff --git a/propel-dist.yaml b/propel-dist.yaml deleted file mode 100644 index e88311b..0000000 --- a/propel-dist.yaml +++ /dev/null @@ -1,32 +0,0 @@ -propel: - database: - connections: - default: - adapter: mysql - classname: Propel\Runtime\Connection\ConnectionWrapper - dsn: "mysql:host=DATABASE_HOST;dbname=DATABASE_NAME" - user: "DATABASE_USER" - password: "DATABASE_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" - - 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 From 6c12f92fd16bb00000c4fe38eb5584f7fa0f2db4 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 11:48:31 +0200 Subject: [PATCH 43/79] New configuration process --- README.md | 63 +++++++------------------------------------------------ 1 file changed, 8 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index b854ff3..c10a24e 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Requirements * PHP >= 5.4 * GIT -* MySQL, PostgreSQL or SQLite +* MySQL or SQLite (PostgreSQL should works) * Composer (php) * Bower (node) @@ -74,43 +74,19 @@ Installation $ git clone https://gitnet.fr/deblan/gist $ cd gist $ make - $ cp propel-dist.yaml propel.yaml -Edit `propel.yaml`. **Use spaces instead of tabulations**. +An interactive shell will start. If you want to perform a manual configuration, follow these instructions. -**MySQL** +If you want to use `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" + $ cp app/config/propel.yaml.dist-mysql propel.yaml - [...] +If you want to use `SQLite`: -**SQLITE** + $ cp app/config/propel.yaml.dist-sqlite propel.yaml - 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`. +Then edit `propel.yaml` and replace the values of `dsn`, `user`, `password` by considering your environment +and run `$ make propel`. **Versions >= 1.4.4 only**: `$ cp app/config/config.yml.dist app/config/config.yml` @@ -379,29 +355,6 @@ Console * **List your gists**: `$ app/console --help gists` * **Delete a gist**: `$ app/console --help delete` -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 ------------ From 8caff598e8926eade3baf41d80f73937baedb72a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 8 Aug 2018 12:41:08 +0200 Subject: [PATCH 44/79] Migration from bower to npm only --- .bowerrc | 3 -- .gitignore | 2 +- Makefile | 35 ++++++++----------- README.md | 27 ++++++++++---- bower.json | 22 ------------ package.json | 9 +++++ .../Resources/views/View/revisions.html.twig | 2 +- web/components/bootstrap | 1 + web/components/diff | 1 + web/components/flag-icon-css | 1 + web/components/iframe-resizer | 1 + web/components/jquery | 1 + 12 files changed, 50 insertions(+), 55 deletions(-) delete mode 100644 .bowerrc delete mode 100644 bower.json create mode 100644 package.json create mode 120000 web/components/bootstrap create mode 120000 web/components/diff create mode 120000 web/components/flag-icon-css create mode 120000 web/components/iframe-resizer create mode 120000 web/components/jquery diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 7f6b222..0000000 --- a/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "web/components/" -} diff --git a/.gitignore b/.gitignore index 0d685da..f5e2c76 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,8 @@ /propel.yaml /src/Gist/Model/Base/ /src/Gist/Model/Map/ -/web/components/ /app/propel/ +/node_modules/ /app/config/config.yml /app/config/propel/ /data/ diff --git a/Makefile b/Makefile index 7dd29cc..9edb0c5 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ COMPOSER ?= composer -BOWER ?= bower +NPM ?= npm GIT ?= git MKDIR ?= mkdir PHP ?= php @@ -7,47 +7,40 @@ PHP ?= php all: update composer: - @echo "Installing application's dependencies" - @echo "-------------------------------------" - @echo + @echo "Installing PHP dependencies" + @echo "---------------------------" + @echo $(COMPOSER) install $(COMPOSER_INSTALL_FLAGS) -bower: - @echo "Installing application's dependencies" - @echo "-------------------------------------" - @echo +npm: + @echo "Installing CSS/JS dependencies" + @echo "------------------------------" + @echo - $(BOWER) install - -optimize: - @echo "Optimizing Composer's autoloader, can take some time" - @echo "----------------------------------------------------" - @echo - - $(COMPOSER) dump-autoload --optimize + $(NPM) install update: @echo "Updating application's dependencies" @echo "-----------------------------------" - @echo + @echo $(GIT) pull origin master ${MKDIR} -p data/git $(COMPOSER) update - $(BOWER) install + $(NPM) install run: @echo "Run development server" @echo "----------------------" - @echo + @echo $(PHP) -S 127.0.0.1:8080 -t web propel: @echo "Propel migration" @echo "----------------" - @echo - + @echo + ./vendor/propel/propel/bin/propel config:convert ./vendor/propel/propel/bin/propel model:build --recursive ./vendor/propel/propel/bin/propel migration:diff --recursive diff --git a/README.md b/README.md index c10a24e..0be2cc2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Table of Contents * [Requirements](#requirements) * [Git](#git) * [Composer](#composer) - * [Bower](#bower) + * [NPM](#npm) * [Installation](#installation) * [Upgrade](#upgrade) * [Configuration](#configuration) @@ -34,7 +34,7 @@ Requirements * GIT * MySQL or SQLite (PostgreSQL should works) * Composer (php) -* Bower (node) +* NPM (nodejs) ### Git @@ -62,10 +62,9 @@ Else, follow the next instructions: # For a global installation $ sudo mv composer.phar /usr/local/bin/composer -### Bower +### NPM $ sudo apt-get install npm - $ sudo npm install -g bower Installation ------------ @@ -162,12 +161,26 @@ 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` will install dependencies via composer and NPM +* `make composer` will install PHP dependencies via composer +* `make npm` will install CSS/JS dependencies via NPM * `make update` will update the application -* `make propel` will generate propel's files +* `make propel` will generate propel migrations (database and files) * `make run` will run development server on http://127.0.0.1:8080/ +By default, `composer`, `npm`, `git`, `mkdir` and `php` binaries must be in your `$PATH`. You can override it by using these envars: + +* `COMPOSER` +* `NPM` +* `GIT` +* `MKDIR` +* `PHP` + +For example: + + $ export COMPOSER=/path/to/composer + $ make composer + API --- diff --git a/bower.json b/bower.json deleted file mode 100644 index 464be4d..0000000 --- a/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "gist", - "version": "0.0.3", - "authors": [ - "Simon Vieille " - ], - "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", - "iframe-resizer": "2.8.6", - "jsdiff": "~2.2.2", - "Prism": "~1.8.1" - } -} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fcb0414 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "bootstrap": "^3.3.4", + "diff": "^2.2.2", + "flag-icon-css": "^0.8.6", + "iframe-resizer": "^2.8.6", + "jquery": "^1.9.1" + } +} diff --git a/src/Gist/Resources/views/View/revisions.html.twig b/src/Gist/Resources/views/View/revisions.html.twig index e1d2766..3b8c2b4 100644 --- a/src/Gist/Resources/views/View/revisions.html.twig +++ b/src/Gist/Resources/views/View/revisions.html.twig @@ -82,7 +82,7 @@ {% if gist.cipher %} - + - + From 418d150833ce86775f3893f22eff8caf9f719ea2 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 12:30:33 +0200 Subject: [PATCH 47/79] Fix issue with SQLite setup --- app/config/propel.yaml.dist-sqlite | 3 +-- src/Gist/Composer/PostInstallHandler.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/config/propel.yaml.dist-sqlite b/app/config/propel.yaml.dist-sqlite index 8580a0b..b11f6c7 100644 --- a/app/config/propel.yaml.dist-sqlite +++ b/app/config/propel.yaml.dist-sqlite @@ -2,7 +2,7 @@ propel: database: connections: default: - adapter: mysql + adapter: sqlite classname: Propel\Runtime\Connection\ConnectionWrapper dsn: "sqlite:DATABASE_PATH" user: ~ @@ -10,7 +10,6 @@ propel: 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" paths: projectDir: src/ diff --git a/src/Gist/Composer/PostInstallHandler.php b/src/Gist/Composer/PostInstallHandler.php index 81650a0..366cc24 100644 --- a/src/Gist/Composer/PostInstallHandler.php +++ b/src/Gist/Composer/PostInstallHandler.php @@ -65,7 +65,7 @@ class PostInstallHandler $question = new Question('Password: [] ', ''); $substitutions['DATABASE_PASSWORD'] = $helper->ask($input, $output, $question); } elseif ($dbms === 'SQLite') { - $defaultPath = getcwd().'/app/data/gist.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'; From 3b812523a923c9548372f3ded993babc47f348c1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 12:33:49 +0200 Subject: [PATCH 48/79] Documentation --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0be2cc2..d6648ec 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,10 @@ If you want to use `SQLite`: Then edit `propel.yaml` and replace the values of `dsn`, `user`, `password` by considering your environment and run `$ make propel`. +If you want to run the interactive shell manually, run: + + $ composer gist-scripts + **Versions >= 1.4.4 only**: `$ cp app/config/config.yml.dist app/config/config.yml` See the [configuration section](#configuration) for more information about configuration. From 32f01bcd753b0eea58a77393a82d34b94af9cf25 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 12:34:47 +0200 Subject: [PATCH 49/79] Documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6648ec..f89201c 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ Console * **Create a gist**: `$ app/console --help create` * **Update a gist**: `$ app/console --help update` -* **Create user**: `app/console --help user:create` +* **Create user**: `$ app/console --help user:create` * **Show stats**: `$ app/console --help stats` ### Version >= v1.7.0 From 999b4a25a7fd5dc73a6468957ae2a6751b683953 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 12:50:58 +0200 Subject: [PATCH 50/79] Documentation --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f89201c..6d32a19 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ https://www.deblan.io/post/517/gist-est-dans-la-place Requirements ------------ -* PHP >= 5.4 +* PHP >= 5.4 with PDO * GIT -* MySQL or SQLite (PostgreSQL should works) +* MySQL or SQLite (PostgreSQL should work) * Composer (php) * NPM (nodejs) @@ -64,7 +64,7 @@ Else, follow the next instructions: ### NPM - $ sudo apt-get install npm + $ sudo apt install npm Installation ------------ @@ -74,22 +74,21 @@ Installation $ cd gist $ make -An interactive shell will start. If you want to perform a manual configuration, follow these instructions. +An interactive shell will start. If you want to run the interactive shell manually, run: -If you want to use `MySQL`: + $ composer gist-scripts + +To perform a manual configuration, follow these instructions. + +With `MySQL`: $ cp app/config/propel.yaml.dist-mysql propel.yaml -If you want to use `SQLite`: +With `SQLite`: $ cp app/config/propel.yaml.dist-sqlite propel.yaml -Then edit `propel.yaml` and replace the values of `dsn`, `user`, `password` by considering your environment -and run `$ make propel`. - -If you want to run the interactive shell manually, run: - - $ composer gist-scripts +Then edit `propel.yaml` and replace the values of `dsn`, `user`, `password` by considering your environment and run `$ make propel`. **Versions >= 1.4.4 only**: `$ cp app/config/config.yml.dist app/config/config.yml` @@ -116,9 +115,9 @@ If your version is less than v1.4.2, run: `test -d app && git add app && git com $ make update $ make propel -If you upgrade to v1.4.1 or more: `app/console migrate:to:v1.4.1`. +If you upgrade from <= v1.4.0 to >= v1.4.1: `app/console migrate:to:v1.4.1`. -If you upgrade to v1.4.4 or more, the configuration is moved to a `app/config/config.yml`: `$ cp app/config/config.yml.dist app/config/config.yml` and see the [configuration section](#configuration) for more information. +If you upgrade from <= v1.4.3 to >= v1.4.4, the configuration is moved to `app/config/config.yml`: `$ cp app/config/config.yml.dist app/config/config.yml` and see the [configuration section](#configuration) for more information. If you upgrade to v1.7.0 or more, see the [configuration section](#configurationh) for more information about new options. From af30221295668e2c005d75818fb8fb5c38b4e3d6 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 14:00:12 +0200 Subject: [PATCH 51/79] Documentation moved to the WIKI --- README.md | 381 +----------------------------------------------------- 1 file changed, 2 insertions(+), 379 deletions(-) diff --git a/README.md b/README.md index 6d32a19..d10b493 100644 --- a/README.md +++ b/README.md @@ -1,388 +1,11 @@ -Table of Contents -================= - - * [GIST](#gist) - * [Requirements](#requirements) - * [Git](#git) - * [Composer](#composer) - * [NPM](#npm) - * [Installation](#installation) - * [Upgrade](#upgrade) - * [Configuration](#configuration) - * [Makefile](#makefile) - * [API](#api) - * [Console](#console) - * [Deployment](#deployment) - * [Contributors](#contributors) - - GIST ==== GIST is an open-source application to share code. https://www.deblan.io/post/517/gist-est-dans-la-place +[Read the wiki for more information](https://gitnet.fr/deblan/gist/wiki/_pages). + ![Gist](https://upload.deblan.org/u/2015-11/565b93a5.png "Gist") ![Gist](https://upload.deblan.org/u/2016-06/57655dec.png "Gist") - - -Requirements ------------- - -* PHP >= 5.4 with PDO -* GIT -* MySQL or SQLite (PostgreSQL should work) -* Composer (php) -* NPM (nodejs) - -### Git - -Git can maybe be downloaded from your system's repositories. - - $ git config --global user.email "you@example.com" - $ git config --global user.name "Your Name" - -### Composer - -Composer can maybe be downloaded from your system's repositories. -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 - -### NPM - - $ sudo apt install npm - -Installation ------------- - - $ cd /path/to/www/ - $ git clone https://gitnet.fr/deblan/gist - $ cd gist - $ make - -An interactive shell will start. If you want to run the interactive shell manually, run: - - $ composer gist-scripts - -To perform a manual configuration, follow these instructions. - -With `MySQL`: - - $ cp app/config/propel.yaml.dist-mysql propel.yaml - -With `SQLite`: - - $ cp app/config/propel.yaml.dist-sqlite propel.yaml - -Then edit `propel.yaml` and replace the values of `dsn`, `user`, `password` by considering your environment and run `$ make propel`. - -**Versions >= 1.4.4 only**: `$ cp app/config/config.yml.dist app/config/config.yml` - -See the [configuration section](#configuration) for more information about configuration. - ---- - -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 - -`app_dev.php` is the development router. Access is granted for an IP range defined in the same file. - -Upgrade -------- - -If your version is less than v1.4.2, run: `test -d app && git add app && git commit -m "Configuration"`. - - $ make update - $ make propel - -If you upgrade from <= v1.4.0 to >= v1.4.1: `app/console migrate:to:v1.4.1`. - -If you upgrade from <= v1.4.3 to >= v1.4.4, the configuration is moved to `app/config/config.yml`: `$ cp app/config/config.yml.dist app/config/config.yml` and see the [configuration section](#configuration) for more information. - -If you upgrade to v1.7.0 or more, see the [configuration section](#configurationh) for more information about new options. - -Configuration -------------- - -### Version < 1.4.4 - -Edit `app/bootstrap.php.d/70-security.php`. - -* `$app['token']`: the securty token (a strong passphrase). -* `$app['enable_registration']`: defines if the registration is allowed (`true` or `false`) -* `$app['enable_login']`: defines if the login is allowed (`true` or `false`) -* `$app['login_required_to_edit_gist']`: defines if the user must be logged to create or clone a Gist (`true` or `false`) -* `$app['login_required_to_view_gist']`: defines if the user must be logged to view a Gist (`true` or `false`) -* `$app['login_required_to_view_gist']`: defines if the user must be logged to view an embeded Gist (`true` or `false`) - -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/`. - -### Version >= 1.4.4 - -Edit `app/config/config.yml`. - -* `security.token`: the securty token (a strong passphrase) -* `security.enable_registration`: defines if the registration is allowed (`true` or `false`) -* `security.enable_login`: defines if the login is allowed (`true` or `false`) -* `security.login_required_to_edit_gist`: defines if the user must be logged to create or clone a Gist (`true` or `false`) -* `security.login_required_to_view_gist`: defines if the user must be logged to view a Gist (`true` or `false`) -* `security.login_required_to_view_gist`: defines if the user must be logged to view an embeded Gist (`true` or `false`) -* `api.base_uri`: The url of your instance. -* `data.path`: the path where the files are saved. -* `git.path`: The path of `git`. -* `theme.name`: the name of the theme (`dark` or `light`) - -### Version >= v1.7.0 - -* `api.enabled`: defines if the API is enabled (`true` or `false`) -* `api.api_key_required`: defines if the API key is required to access the API (`true` or `false`) -* `api.client.api_key`: defines the client API key (`string`) - -Makefile --------- - -A Makefile is provided to automate some tasks. - -* `make` will install dependencies via composer and NPM -* `make composer` will install PHP dependencies via composer -* `make npm` will install CSS/JS dependencies via NPM -* `make update` will update the application -* `make propel` will generate propel migrations (database and files) -* `make run` will run development server on http://127.0.0.1:8080/ - -By default, `composer`, `npm`, `git`, `mkdir` and `php` binaries must be in your `$PATH`. You can override it by using these envars: - -* `COMPOSER` -* `NPM` -* `GIT` -* `MKDIR` -* `PHP` - -For example: - - $ export COMPOSER=/path/to/composer - $ make composer - -API ---- - -### Version < v1.7.0 - -#### 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 `405`: Method Not Allowed -* Code `400`: Bad Request -* 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" - } -} -``` - -#### Update an existing gist - -**POST** /{locale}/api/update/{id} -Params: - -* `{id}`: Gist Id (required) -* `form[content]`: String (required) - -**Responses:** - -* Code `405`: Method Not Allowed -* Code `400`: Bad Request -* 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" - } -} -``` - -### Version >= v1.7.0 - -Invalid response codes: - -* Code `401`: Unauthorized -* Code `403`: API not enabled -* Code `405`: Method Not Allowed -* Code `400`: Bad Request - -#### List gists - -**GET** /{locale}/api/list/{apiToken} - -Response example: - -```javascript -[ - { - "id": 66, - "title": "test prod", - "cipher": false, - "type": "javascript", - "file": "55abcfa7771e0", - "createdAt": "2015-07-19T16:26:15Z", - "updatedAt": "2015-07-19T16:30:15Z" - "url": "https:\/\/gist.deblan.org\/en\/view\/55abcfa7771e0\/abcgi72967dd95e3461490dcaa310d728d6adef", - }, - { - "id": 67, - "title": "test prod 2", - "cipher": false, - "type": "javascript", - "file": "xyzbcfa7771e0", - "createdAt": "2015-08-19T16:26:15Z", - "updatedAt": "2015-08-19T16:30:15Z" - "url": "https:\/\/gist.deblan.org\/en\/view\/5byzbcfa7771e0\/def72967dd95e346koq0dcaa310d728d6artu", - }, - ... -] -``` - -#### Create a new gist - -**POST** /{locale}/api/create/{apiToken} -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) - -Response 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" - } -} -``` - -#### Update an existing gist - -**POST** /{locale}/api/update/{id}/{apiToken} -Params: - -* `{id}`: Gist Id (required) -* `form[content]`: String (required) - -Response 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" - } -} -``` - -#### Delete an existing gist - -**POST** /{locale}/api/delete/{id}/{apiToken} - -Response code `200`: - -```javascript -{"error":false} -``` - -Response code `400`: - -```javascript -{"message":"Invalid Gist", "error":true} -``` - -Console -------- - -* **Create a gist**: `$ app/console --help create` -* **Update a gist**: `$ app/console --help update` -* **Create user**: `$ app/console --help user:create` -* **Show stats**: `$ app/console --help stats` - -### Version >= v1.7.0 - -* **List your gists**: `$ app/console --help gists` -* **Delete a gist**: `$ app/console --help delete` - -Contributors ------------- - -**Developers** - -* Simon Vieille - -**Translators** - -* Simon Vieille -* Marion Sanchez -* Marjorie Da Silva -* Mélanie Chanat -* Showfom -* Tavin From 2d8f19437a0635ca7ea238705a07553e8ad40074 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 16:02:08 +0200 Subject: [PATCH 52/79] Fix issue with prism path on embed page --- src/Gist/Resources/views/View/embed.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index 44ff7df..bc7ae39 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -3,7 +3,7 @@ {% block css %} {{ parent() }} - + {% if theme_settings.name == 'dark' %} From b7e6d8c69c9c083ce1981d8749f39e3ef7c68ec2 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 16:40:04 +0200 Subject: [PATCH 53/79] HTTP Cache --- .gitignore | 1 + Makefile | 1 + app/bootstrap.php.d/20-twig.php | 2 +- app/bootstrap.php.d/80-cache.php | 7 +++++++ src/Gist/Controller/Controller.php | 10 +++++++++- web/index.php | 2 +- 6 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 app/bootstrap.php.d/80-cache.php diff --git a/.gitignore b/.gitignore index f5e2c76..6d98c4e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ /app/config/propel/ /data/ /trans/ +/cache/ diff --git a/Makefile b/Makefile index 9edb0c5..8bf831b 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ update: $(GIT) pull origin master ${MKDIR} -p data/git + ${MKDIR} -p data/cache $(COMPOSER) update $(NPM) install diff --git a/app/bootstrap.php.d/20-twig.php b/app/bootstrap.php.d/20-twig.php index 8da7180..e69e1c6 100644 --- a/app/bootstrap.php.d/20-twig.php +++ b/app/bootstrap.php.d/20-twig.php @@ -9,6 +9,6 @@ $app->register(new TwigServiceProvider(), array( $app->extend('twig', function ($twig, $app) { $base = str_replace($app['request']->server->get('SCRIPT_NAME'), '', $app['request']->getBaseUrl()); $twig->addGlobal('web_path', $base.'/'); - + return $twig; }); diff --git a/app/bootstrap.php.d/80-cache.php b/app/bootstrap.php.d/80-cache.php new file mode 100644 index 0000000..3013cd6 --- /dev/null +++ b/app/bootstrap.php.d/80-cache.php @@ -0,0 +1,7 @@ +register(new HttpCacheServiceProvider(), array( + 'http_cache.cache_dir' => $app['root_path'].'/cache/', +)); diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index 5e71381..7cbcccd 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -175,9 +175,17 @@ abstract class Controller $params['user'] = $this->getUser(); } - return $app['twig']->render( + $body = $app['twig']->render( $template, $params ); + + $response = new Response($body); + + if (empty($params['no_cache'])) { + $response->setTtl(3600 * 24 * 7); + } + + return $response; } } diff --git a/web/index.php b/web/index.php index 5dd7e92..d66b7a8 100644 --- a/web/index.php +++ b/web/index.php @@ -4,4 +4,4 @@ $app = require __DIR__.'/../app/bootstrap.php'; $app['env'] = 'prod'; -$app->run(); +$app['http_cache']->run(); From 2ac973740921bf7909da8b7c4ee4c088a903b5f5 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 20 Aug 2018 17:05:36 +0200 Subject: [PATCH 54/79] Cache control --- app/bootstrap.php.d/80-cache.php | 1 + src/Gist/Controller/Controller.php | 8 ++++++-- src/Gist/Controller/EditController.php | 5 +++-- src/Gist/Controller/LoginController.php | 4 ++-- src/Gist/Controller/MyController.php | 3 ++- src/Gist/Controller/ViewController.php | 13 +++++++------ 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/app/bootstrap.php.d/80-cache.php b/app/bootstrap.php.d/80-cache.php index 3013cd6..3a28362 100644 --- a/app/bootstrap.php.d/80-cache.php +++ b/app/bootstrap.php.d/80-cache.php @@ -4,4 +4,5 @@ use Silex\Provider\HttpCacheServiceProvider; $app->register(new HttpCacheServiceProvider(), array( 'http_cache.cache_dir' => $app['root_path'].'/cache/', + 'http_cache.esi' => null, )); diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index 7cbcccd..b77fa11 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -136,7 +136,6 @@ abstract class Controller $app = $this->getApp(); if (!empty($request)) { - } $securityContext = $app['security.token_storage']; @@ -160,10 +159,11 @@ abstract class Controller * * @param string $template * @param array $params + * @param bool $renderResponse * * @return string */ - public function render($template, array $params = null) + public function render($template, array $params = null, $renderResponse = true) { $app = $this->getApp(); @@ -180,6 +180,10 @@ abstract class Controller $params ); + if (!$renderResponse) { + return $body; + } + $response = new Response($body); if (empty($params['no_cache'])) { diff --git a/src/Gist/Controller/EditController.php b/src/Gist/Controller/EditController.php index 1767dce..cc7271f 100644 --- a/src/Gist/Controller/EditController.php +++ b/src/Gist/Controller/EditController.php @@ -9,6 +9,7 @@ use Gist\Model\Gist; use GitWrapper\GitException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Form\FormError; +use Symfony\Component\HttpFoundation\Response; /** * Class EditController. @@ -22,7 +23,7 @@ class EditController extends Controller * * @param Request $request * - * @return string + * @return Response */ public function createAction(Request $request) { @@ -68,7 +69,7 @@ class EditController extends Controller * * @param Request $request * - * @return string + * @return Response */ public function cloneAction(Request $request, $gist, $commit) { diff --git a/src/Gist/Controller/LoginController.php b/src/Gist/Controller/LoginController.php index f835306..5547be3 100644 --- a/src/Gist/Controller/LoginController.php +++ b/src/Gist/Controller/LoginController.php @@ -20,7 +20,7 @@ class LoginController extends Controller * * @param Request $request * - * @return string + * @return Response */ public function registerAction(Request $request) { @@ -72,7 +72,7 @@ class LoginController extends Controller * * @param Request $request * - * @return string + * @return Response */ public function loginAction(Request $request) { diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index d59f315..9b4a170 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -7,6 +7,7 @@ use Gist\Form\DeleteGistForm; use Gist\Form\FilterGistForm; use Gist\Form\UserPasswordForm; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Response; /** * Class MyController. @@ -21,7 +22,7 @@ class MyController extends Controller * @param Request $request * @param int $page * - * @return string + * @return Response */ public function myAction(Request $request, $page) { diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index 44aeedc..d80d3b3 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -66,14 +66,14 @@ class ViewController extends Controller * @param string $gist Gist's ID * @param string $commit The commit * - * @return string|Response + * @return Response */ public function embedJsAction(Request $request, $gist, $commit) { $viewOptions = $this->getViewOptions($request, $gist, $commit); return new Response( - $this->render('View/embedJs.html.twig', $viewOptions), + $this->render('View/embedJs.html.twig', $viewOptions, false), 200, array( 'Content-Type' => 'text/javascript', @@ -88,7 +88,7 @@ class ViewController extends Controller * @param string $gist Gist's ID * @param string $commit The commit * - * @return string|Response + * @return Response */ public function rawAction(Request $request, $gist, $commit) { @@ -114,7 +114,7 @@ class ViewController extends Controller * @param string $gist Gist's ID * @param string $commit The commit * - * @return string|Response + * @return Response */ public function downloadAction(Request $request, $gist, $commit) { @@ -133,7 +133,8 @@ class ViewController extends Controller 'Content-Disposition' => sprintf('filename=%s.%s', $gist->getFile(), $gist->getTypeAsExtension()), 'Content-Length' => mb_strlen($viewOptions['raw_content']), 'Content-Type' => 'application/force-download', - ) + ), + false ); } else { return $this->notFoundResponse($app); @@ -146,7 +147,7 @@ class ViewController extends Controller * @param Request $request * @param string $gist Gist's ID * - * @return string|Response + * @return Response */ public function revisionsAction(Request $request, $gist) { From b43baac802bd6cdd4ead4f84c93bb8619596a2ec Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 21 Aug 2018 09:56:51 +0200 Subject: [PATCH 55/79] Cache --- src/Gist/Controller/Controller.php | 20 ++++++++++++++------ src/Gist/Controller/EditController.php | 4 ++-- src/Gist/Controller/LoginController.php | 4 ++-- src/Gist/Controller/MyController.php | 2 +- src/Gist/Controller/ViewController.php | 8 ++++---- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index b77fa11..d239e5c 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -159,11 +159,10 @@ abstract class Controller * * @param string $template * @param array $params - * @param bool $renderResponse * * @return string */ - public function render($template, array $params = null, $renderResponse = true) + public function render($template, array $params = null) { $app = $this->getApp(); @@ -175,14 +174,23 @@ abstract class Controller $params['user'] = $this->getUser(); } - $body = $app['twig']->render( + return $app['twig']->render( $template, $params ); + } - if (!$renderResponse) { - return $body; - } + /** + * 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); diff --git a/src/Gist/Controller/EditController.php b/src/Gist/Controller/EditController.php index cc7271f..0eb82d6 100644 --- a/src/Gist/Controller/EditController.php +++ b/src/Gist/Controller/EditController.php @@ -55,7 +55,7 @@ class EditController extends Controller } } - return $this->render( + return $this->createResponse( 'Edit/index.html.twig', array( 'gist' => isset($gist) ? $gist : null, @@ -110,6 +110,6 @@ class EditController extends Controller $viewOptions['form'] = $form->createView(); - return $this->render('Edit/clone.html.twig', $viewOptions); + return $this->createResponse('Edit/clone.html.twig', $viewOptions); } } diff --git a/src/Gist/Controller/LoginController.php b/src/Gist/Controller/LoginController.php index 5547be3..6732462 100644 --- a/src/Gist/Controller/LoginController.php +++ b/src/Gist/Controller/LoginController.php @@ -57,7 +57,7 @@ class LoginController extends Controller } } - return $this->render( + return $this->createResponse( 'Login/register.html.twig', [ 'form' => $form->createView(), @@ -97,7 +97,7 @@ class LoginController extends Controller $error = $app['translator']->trans('login.login.invalid'); } - return $this->render( + return $this->createResponse( 'Login/login.html.twig', [ 'form' => $form->createView(), diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index 9b4a170..3367ffa 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -120,7 +120,7 @@ class MyController extends Controller } } - return $this->render( + return $this->createResponse( 'My/my.html.twig', array( 'gists' => $gists, diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index d80d3b3..48c9a75 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -31,7 +31,7 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); if (is_array($viewOptions)) { - return $this->render('View/view.html.twig', $viewOptions); + return $this->createResponse('View/view.html.twig', $viewOptions); } else { return $this->notFoundResponse(); } @@ -53,7 +53,7 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); if (is_array($viewOptions)) { - return $app['twig']->render('View/embed.html.twig', $viewOptions); + return $app['twig']->createResponse('View/embed.html.twig', $viewOptions); } else { return $this->notFoundResponse(); } @@ -73,7 +73,7 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); return new Response( - $this->render('View/embedJs.html.twig', $viewOptions, false), + $this->render('View/embedJs.html.twig', $viewOptions), 200, array( 'Content-Type' => 'text/javascript', @@ -165,7 +165,7 @@ class ViewController extends Controller return $this->notFoundResponse(); } - return $this->render( + return $this->createResponse( 'View/revisions.html.twig', array( 'gist' => $gist, From 6e848f0982905569dcf462bbf41eb63ef1fcff5b Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 21 Aug 2018 10:01:33 +0200 Subject: [PATCH 56/79] Cache --- src/Gist/Controller/Controller.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index d239e5c..cc1a627 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -195,7 +195,9 @@ abstract class Controller $response = new Response($body); if (empty($params['no_cache'])) { - $response->setTtl(3600 * 24 * 7); + $ttl = 3600 * 24 * 7; + $response->setTtl($ttl); + $response->setClientTtl($ttl); } return $response; From 001901a8f745cf7cf762abc507001d2020c2313c Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 21 Aug 2018 10:13:38 +0200 Subject: [PATCH 57/79] Fix issue with ViewController --- src/Gist/Controller/ViewController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index 48c9a75..d3be5bd 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -53,7 +53,7 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); if (is_array($viewOptions)) { - return $app['twig']->createResponse('View/embed.html.twig', $viewOptions); + return $this->createResponse('View/embed.html.twig', $viewOptions); } else { return $this->notFoundResponse(); } From f36783b2cea27579337e78e1a1f4276a6282dd0b Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 21 Aug 2018 10:24:26 +0200 Subject: [PATCH 58/79] Cache --- src/Gist/Controller/Controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index cc1a627..ee840a7 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -198,6 +198,7 @@ abstract class Controller $ttl = 3600 * 24 * 7; $response->setTtl($ttl); $response->setClientTtl($ttl); + $response->setExpires(new \DateTime('now +7 days')); } return $response; From fbac488f62179e06b181bc1ae63e384adc504bb0 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 21 Aug 2018 16:10:20 +0200 Subject: [PATCH 59/79] New HTTP Cache headers and cache disabled for account page --- src/Gist/Controller/Controller.php | 4 ++++ src/Gist/Controller/MyController.php | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index ee840a7..6babb1c 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -196,9 +196,13 @@ abstract class Controller 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; diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index 3367ffa..478ba43 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -130,6 +130,7 @@ class MyController extends Controller 'filterForm' => $filterForm->createView(), 'passwordForm' => $passwordForm->createView(), 'deleted' => !empty($deleted), + 'no_cache' => true, ) ); } From 971812f2d8238e84934c0022ce5675092342c5a1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 21 Aug 2018 16:21:23 +0200 Subject: [PATCH 60/79] Pictures in README --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d10b493..ccbff71 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,20 @@ GIST GIST is an open-source application to share code. https://www.deblan.io/post/517/gist-est-dans-la-place -[Read the wiki for more information](https://gitnet.fr/deblan/gist/wiki/_pages). +**[Read the wiki for more information](https://gitnet.fr/deblan/gist/wiki/_pages).** -![Gist](https://upload.deblan.org/u/2015-11/565b93a5.png "Gist") +### Editor -![Gist](https://upload.deblan.org/u/2016-06/57655dec.png "Gist") +![Gist](https://upload.deblan.org/u/2018-08/5b7ab7a6.png "Gist editor") + +### Result + +![Gist](https://upload.deblan.org/u/2018-08/5b7ab7d4.png "Gist result") + +### Account + +![Gist](https://upload.deblan.org/u/2018-08/5b7aba2d.png "Gist account") + +### Embeded Gist + +![Gist](https://upload.deblan.org/u/2018-08/5b7ab81c.png "Embeded Gist") From 0eb689b5dc744206e4e2ca024ce13f3a959dc3d3 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 5 Sep 2018 11:08:44 +0200 Subject: [PATCH 61/79] API's document links updated --- app/locales/cn.yml | 2 +- app/locales/de.yml | 2 +- app/locales/en.yml | 2 +- app/locales/es.yml | 2 +- app/locales/fr.yml | 2 +- app/locales/pl.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/locales/cn.yml b/app/locales/cn.yml index 9af2b92..1dbaee3 100644 --- a/app/locales/cn.yml +++ b/app/locales/cn.yml @@ -44,7 +44,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Powered by GIST, it''s open source :) - API

    ' + text: '

    Powered by GIST, it''s open source :) - API

    ' login: login: diff --git a/app/locales/de.yml b/app/locales/de.yml index 28a0314..3461653 100644 --- a/app/locales/de.yml +++ b/app/locales/de.yml @@ -44,7 +44,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Powered by GIST, it''s open source :) - API

    ' + text: '

    Powered by GIST, it''s open source :) - API

    ' login: login: diff --git a/app/locales/en.yml b/app/locales/en.yml index dd99aba..18fb7de 100644 --- a/app/locales/en.yml +++ b/app/locales/en.yml @@ -45,7 +45,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Powered by GIST, it''s open source :) - API

    ' + text: '

    Powered by GIST, it''s open source :) - API

    ' login: login: diff --git a/app/locales/es.yml b/app/locales/es.yml index 679d0f1..c315f6e 100644 --- a/app/locales/es.yml +++ b/app/locales/es.yml @@ -44,7 +44,7 @@ date: format: 'd/m/Y H\hi s\s' footer: - text: '

    Impulsado por GIST, es libre :) - API

    ' + text: '

    Impulsado por GIST, es libre :) - API

    ' login: login: diff --git a/app/locales/fr.yml b/app/locales/fr.yml index 68759cd..8788853 100644 --- a/app/locales/fr.yml +++ b/app/locales/fr.yml @@ -44,7 +44,7 @@ date: format: 'd/m/Y H\hi s\s' footer: - text: '

    Propulsé par GIST, c''est libre :) - API

    ' + text: '

    Propulsé par GIST, c''est libre :) - API

    ' login: login: diff --git a/app/locales/pl.yml b/app/locales/pl.yml index e250227..d404f11 100644 --- a/app/locales/pl.yml +++ b/app/locales/pl.yml @@ -45,7 +45,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Napędzane przez GIST, to jest open source :) - API

    ' + text: '

    Napędzane przez GIST, to jest open source :) - API

    ' login: login: From 7f77b92554e26aec7c26611f3a228db2eeed4049 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 5 Sep 2018 12:16:29 +0200 Subject: [PATCH 62/79] Feature: line-numbers, UI: target blank on embed links --- src/Gist/Resources/views/View/embed.html.twig | 12 ++--- src/Gist/Resources/views/View/view.html.twig | 2 +- web/app/css/themes/dark.css | 8 +++ web/app/css/themes/light.css | 8 +++ web/app/js/prism.js | 52 +++++++++---------- 5 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index bc7ae39..b1014b6 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -55,18 +55,18 @@ {% if not gist.cipher %}
  • - + {{ 'gist.action.raw'|trans }}
  • - + {{ 'gist.action.download'|trans }}
  • {% endif %}
  • - + {{ 'gist.action.clone'|trans }}
  • @@ -78,17 +78,17 @@ {{ commit|slice(0, 10) }} {% if not gist.cipher %} - + {{ 'gist.action.raw'|trans }} - + {{ 'gist.action.download'|trans }} {% endif %} - + {{ 'gist.action.clone'|trans }} diff --git a/src/Gist/Resources/views/View/view.html.twig b/src/Gist/Resources/views/View/view.html.twig index 33dbc7e..29ffc5d 100644 --- a/src/Gist/Resources/views/View/view.html.twig +++ b/src/Gist/Resources/views/View/view.html.twig @@ -101,7 +101,7 @@
    -
    {{ raw_content }}
    +
    {{ raw_content }}
    diff --git a/web/app/css/themes/dark.css b/web/app/css/themes/dark.css index ab05c08..22c0060 100644 --- a/web/app/css/themes/dark.css +++ b/web/app/css/themes/dark.css @@ -56,3 +56,11 @@ body { .btn-error:active, .btn-error:hover, .btn-error:focus { color: #000; } + +pre.line-numbers { + padding-left: 50px !important; +} + +.line-numbers-rows { + top: -4px !important; +} diff --git a/web/app/css/themes/light.css b/web/app/css/themes/light.css index 9c07b5b..71bcfc7 100644 --- a/web/app/css/themes/light.css +++ b/web/app/css/themes/light.css @@ -46,3 +46,11 @@ pre, code { .btn-error:active, .btn-error:hover, .btn-error:focus { color: #000; } + +pre.line-numbers { + padding-left: 50px !important; +} + +.line-numbers-rows { + top: -4px !important; +} diff --git a/web/app/js/prism.js b/web/app/js/prism.js index bfb1dca..ffc8935 100644 --- a/web/app/js/prism.js +++ b/web/app/js/prism.js @@ -1,29 +1,25 @@ -/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+actionscript+c+aspnet+bash+cpp+csharp+css-extras+diff+perl+php+php-extras+python+sql+yaml&plugins=line-highlight+line-numbers+autolinker+previewer-base+previewer-color+previewer-gradient+previewer-easing+previewer-time+previewer-angle */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){h.lastIndex=0;var _=h.exec(w),P=1;if(!_&&m&&b!=t.length-1){if(h.lastIndex=k,_=h.exec(e),!_)break;for(var A=_.index+(d?_[1].length:0),j=_.index+_[0].length,x=b,O=k,S=t.length;S>x&&(j>O||!t[x].type&&!t[x-1].greedy);++x)O+=t[x].length,A>=O&&(++b,k=O);if(t[b]instanceof s||t[x-1].greedy)continue;P=x-b,w=e.slice(k,O),_.index-=k}if(_){d&&(p=_[1].length);var A=_.index+p,_=_[0].slice(p),j=A+_.length,N=w.slice(0,A),C=w.slice(j),E=[b,P];N&&(++b,k+=N.length,E.push(N));var I=new s(u,f?n.tokenize(_,f):_,y,_,m);if(E.push(I),C&&E.push(C),Array.prototype.splice.apply(t,E),1!=P&&n.matchGrammar(e,t,a,b,k,!0,u),l)break}else if(l)break}}}}},tokenize:function(e,t){var a=[e],r=t.rest;if(r){for(var i in r)t[i]=r[i];delete t.rest}return n.matchGrammar(e,a,t,0,0,!1),a},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var i={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}n.hooks.run("wrap",i);var o=Object.keys(i.attributes).map(function(e){return e+'="'+(i.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(o?" "+o:"")+">"+i.content+""},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,i=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),i&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\s\S]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; -Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); -Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)\s*=>))/i,alias:"function"}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript; -Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\\1|\\?(?!\1)[\s\S])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:Prism.languages.markup}}}); -Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; -Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive tag":{pattern:/<%\s*@.*%>/i,inside:{"page-directive tag":/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,rest:Prism.languages.markup.tag.inside}},"directive tag":{pattern:/<%.*%>/i,inside:{"directive tag":/<%\s*?[$=%#:]{0,2}|%>/i,rest:Prism.languages.csharp}}}),Prism.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("inside","punctuation",{"directive tag":Prism.languages.aspnet["directive tag"]},Prism.languages.aspnet.tag.inside["attr-value"]),Prism.languages.insertBefore("aspnet","comment",{"asp comment":/<%--[\s\S]*?--%>/}),Prism.languages.insertBefore("aspnet",Prism.languages.javascript?"script":"tag",{"asp script":{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.csharp||{}}}); -!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},"boolean":{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a.boolean=e.languages.bash.boolean,a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation}(Prism); -Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(true|false)\b/,operator:/[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)[a-z0-9_]+/i,lookbehind:!0}}); -Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(abstract|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/,string:[{pattern:/@("|')(\1\1|\\\1|\\?(?!\1)[\s\S])*\1/,greedy:!0},{pattern:/("|')(\\?.)*?\1/,greedy:!0}],number:/\b-?(0x[\da-f]+|\d*\.?\d+f?)\b/i}),Prism.languages.insertBefore("csharp","keyword",{"generic-method":{pattern:/[a-z0-9_]+\s*<[^>\r\n]+?>\s*(?=\()/i,alias:"function",inside:{keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}); -Prism.languages.css.selector={pattern:/[^\{\}\s][^\{\}]*(?=\s*\{)/,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:\.\w]+/,id:/#[-:\.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%\.]+/}); +/* 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+perl+php+php-extras+sql+python+yaml&plugins=line-highlight+line-numbers+autolinker */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-([\w-]+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){if(m&&b!=t.length-1){h.lastIndex=k;var _=h.exec(e);if(!_)break;for(var j=_.index+(d?_[1].length:0),P=_.index+_[0].length,A=b,x=k,O=t.length;O>A&&(P>x||!t[A].type&&!t[A-1].greedy);++A)x+=t[A].length,j>=x&&(++b,k=x);if(t[b]instanceof s)continue;I=A-b,w=e.slice(k,x),_.index-=k}else{h.lastIndex=0;var _=h.exec(w),I=1}if(_){d&&(p=_[1]?_[1].length:0);var j=_.index+p,_=_[0].slice(p),P=j+_.length,N=w.slice(0,j),S=w.slice(P),C=[b,I];N&&(++b,k+=N.length,C.push(N));var E=new s(u,f?n.tokenize(_,f):_,y,_,m);if(C.push(E),S&&C.push(S),Array.prototype.splice.apply(t,C),1!=I&&n.matchGrammar(e,t,r,b,k,!0,u),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; +Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css",greedy:!0}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/],number:/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"},constant:/\b[A-Z][A-Z\d_]*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; +Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:Prism.languages.markup}}}); +Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?/,number:/(?:\b0x[\da-f]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; +Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/,string:[{pattern:/@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/,greedy:!0}],"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=\s+\w+)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|interface|new)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)f?/i}),Prism.languages.insertBefore("csharp","class-name",{"generic-method":{pattern:/\w+\s*<[^>\r\n]+?>\s*(?=\()/,inside:{"function":/^\w+/,"class-name":{pattern:/\b[A-Z]\w*(?:\.\w+)*\b/,inside:{punctuation:/\./}},keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.dotnet=Prism.languages.csharp; +!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[\w#?*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)["']?(\w+?)["']?\s*\r?\n(?:[\s\S])*?\r?\n\2/,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|[\s;|&])(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|[\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&])(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\s;|&])/,lookbehind:!0},"boolean":{pattern:/(^|[\s;|&])(?:true|false)(?=$|[\s;|&])/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a.string=e.languages.bash.string,a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a["boolean"]=e.languages.bash["boolean"],a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation,e.languages.shell=e.languages.bash}(Prism); +Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(?:true|false)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)\w+/i,lookbehind:!0}}),Prism.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}); +Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive tag":{pattern:/<%\s*@.*%>/i,inside:{"page-directive tag":/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,rest:Prism.languages.markup.tag.inside}},"directive tag":{pattern:/<%.*%>/i,inside:{"directive tag":/<%\s*?[$=%#:]{0,2}|%>/i,rest:Prism.languages.csharp}}}),Prism.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("inside","punctuation",{"directive tag":Prism.languages.aspnet["directive tag"]},Prism.languages.aspnet.tag.inside["attr-value"]),Prism.languages.insertBefore("aspnet","comment",{"asp comment":/<%--[\s\S]*?--%>/}),Prism.languages.insertBefore("aspnet",Prism.languages.javascript?"script":"tag",{"asp script":{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.csharp||{}}}); +Prism.languages.css.selector={pattern:/[^{}\s][^{}]*(?=\s*\{)/,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%.]+/}); Prism.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d+.*$/m],deleted:/^[-<].*$/m,inserted:/^[+>].*$/m,diff:{pattern:/^!(?!!).+$/m,alias:"important"}}; -Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:[^\\]|\\.)*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?((::)*'?(?!\d)[\w$]+)+(::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(\.\d+)*|\d+(\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b-?(0x[\dA-Fa-f](_?[\dA-Fa-f])*|0b[01](_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; -Prism.languages.php=Prism.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),Prism.languages.insertBefore("php","class-name",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),Prism.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$\w+\b/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),Prism.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}}),Prism.languages.markup&&(Prism.hooks.add("before-highlight",function(e){"php"===e.language&&/(?:<\?php|<\?)/gi.test(e.code)&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi,function(a){for(var n=e.tokenStack.length;-1!==e.backupCode.indexOf("___PHP"+n+"___");)++n;return e.tokenStack[n]=a,"___PHP"+n+"___"}),e.grammar=Prism.languages.markup)}),Prism.hooks.add("before-insert",function(e){"php"===e.language&&e.backupCode&&(e.code=e.backupCode,delete e.backupCode)}),Prism.hooks.add("after-highlight",function(e){if("php"===e.language&&e.tokenStack){e.grammar=Prism.languages.php;for(var a=0,n=Object.keys(e.tokenStack);a'+Prism.highlight(r,e.grammar,"php").replace(/\$/g,"$$$$")+"")}e.element.innerHTML=e.highlightedCode}})); -Prism.languages.insertBefore("php","variable",{"this":/\$this\b/,global:/\$(?:_(?:SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE)|GLOBALS|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/(static|self|parent)/,punctuation:/(::|\\)/}}}); -Prism.languages.python={"triple-quoted-string":{pattern:/"""[\s\S]+?"""|'''[\s\S]+?'''/,alias:"string"},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/("|')(?:\\\\|\\?[^\\\r\n])*?\1/,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,"boolean":/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},string:{pattern:/(^|[^@\\])("|')(?:\\?[\s\S])*?\2/,greedy:!0,lookbehind:!0},variable:/@[\w.$]+|@("|'|`)(?:\\?[\s\S])+?\1/,"function":/\b(?:COUNT|SUM|AVG|MIN|MAX|FIRST|LAST|UCASE|LCASE|MID|LEN|ROUND|NOW|FORMAT)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR VARYING|CHARACTER (?:SET|VARYING)|CHARSET|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|DATA(?:BASES?)?|DATE(?:TIME)?|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITER(?:S)?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE(?: PRECISION)?|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE(?:D BY)?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEYS?|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL(?: CHAR VARYING| CHARACTER(?: VARYING)?| VARCHAR)?|NATURAL|NCHAR(?: VARCHAR)?|NEXT|NO(?: SQL|CHECK|CYCLE)?|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READ(?:S SQL DATA|TEXT)?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START(?:ING BY)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED BY|TEXT(?:SIZE)?|THEN|TIMESTAMP|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNPIVOT|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?)\b/i,"boolean":/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b-?(?:0x)?\d*\.?[\da-f]+\b/,operator:/[-+*\/=%^~]|&&?|\|?\||!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; -Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\3[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(\d{4}-\d\d?-\d\d?([tT]|[ \t]+)\d\d?:\d{2}:\d{2}(\.\d*)?[ \t]*(Z|[-+]\d\d?(:\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(:\d{2}(\.\d*)?)?)(?=[ \t]*($|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')(?=[ \t]*($|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)[+\-]?(0x[\da-f]+|0o[0-7]+|(\d+\.?\d*|\.?\d+)(e[\+\-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}; -!function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){for(var o,a=n.replace(/\s+/g,"").split(","),l=+e.getAttribute("data-line-offset")||0,d=r()?parseInt:parseFloat,c=d(getComputedStyle(e).lineHeight),s=0;o=a[s++];){o=o.split("-");var u=+o[0],m=+o[1]||u,h=document.createElement("div");h.textContent=Array(m-u+2).join(" \n"),h.setAttribute("aria-hidden","true"),h.className=(i||"")+" line-highlight",t(e,"line-numbers")||(h.setAttribute("data-start",u),m>u&&h.setAttribute("data-end",m)),h.style.top=(u-l-1)*c+"px",t(e,"line-numbers")?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML=" 
     ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function(e){var t=e.element.parentNode,r=t&&t.getAttribute("data-line");t&&r&&/pre/i.test(t.nodeName)&&(clearTimeout(o),n(t,r),o=setTimeout(i,1))}),window.addEventListener("hashchange",i)}}(); -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=function(e){var t=n(e),r=t["white-space"];if("pre-wrap"===r||"pre-line"===r){var s=e.querySelector("code"),l=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),i=e.textContent.split("\n");a||(a=document.createElement("span"),a.className="line-numbers-sizer",s.appendChild(a)),a.style.display="block",i.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;l.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},n=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),t)}),Prism.hooks.add("complete",function(e){if(e.code){var n=e.element.parentNode,r=/\s*\bline-numbers\b\s*/;if(n&&/pre/i.test(n.nodeName)&&(r.test(n.className)||r.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){r.test(e.element.className)&&(e.element.className=e.element.className.replace(r," ")),r.test(n.className)||(n.className+=" line-numbers");var s,l=e.code.match(/\n(?!$)/g),a=l?l.length+1:1,i=new Array(a+1);i=i.join(""),s=document.createElement("span"),s.setAttribute("aria-hidden","true"),s.className="line-numbers-rows",s.innerHTML=i,n.hasAttribute("data-start")&&(n.style.counterReset="linenumber "+(parseInt(n.getAttribute("data-start"),10)-1)),e.element.appendChild(s),t(n)}}})}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:#=?&]+/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(a){a&&!a["url-link"]&&(Prism.languages.DFS(a,function(a,r,l){t.indexOf(l)>-1&&"Array"!==Prism.util.type(r)&&(r.pattern||(r=this[a]={pattern:r}),r.inside=r.inside||{},"comment"==l&&(r.inside["md-link"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},r):r.inside["url-link"]=i,r.inside["email-link"]=n)}),a["url-link"]=i,a["email-link"]=n)}},Prism.hooks.add("before-highlight",function(i){Prism.plugins.autolinker.processGrammar(i.grammar)}),Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var t=i.content.match(e);n=t[2],i.content=t[1]}i.attributes.href=n}try{i.content=decodeURIComponent(i.content)}catch(a){}})}}(); -!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&Function.prototype.bind){var t=function(t){var e=0,s=0,i=t;if(i.parentNode){do e+=i.offsetLeft,s+=i.offsetTop;while((i=i.offsetParent)&&i.nodeType<9);i=t;do e-=i.scrollLeft,s-=i.scrollTop;while((i=i.parentNode)&&!/body/i.test(i.nodeName))}return{top:s,right:innerWidth-e-t.offsetWidth,bottom:innerHeight-s-t.offsetHeight,left:e}},e=/(?:^|\s)token(?=$|\s)/,s=/(?:^|\s)active(?=$|\s)/g,i=/(?:^|\s)flipped(?=$|\s)/g,o=function(t,e,s,i){this._elt=null,this._type=t,this._clsRegexp=RegExp("(?:^|\\s)"+t+"(?=$|\\s)"),this._token=null,this.updater=e,this._mouseout=this.mouseout.bind(this),this.initializer=i;var n=this;s||(s=["*"]),"Array"!==Prism.util.type(s)&&(s=[s]),s.forEach(function(t){"string"!=typeof t&&(t=t.lang),o.byLanguages[t]||(o.byLanguages[t]=[]),o.byLanguages[t].indexOf(n)<0&&o.byLanguages[t].push(n)}),o.byType[t]=this};o.prototype.init=function(){this._elt||(this._elt=document.createElement("div"),this._elt.className="prism-previewer prism-previewer-"+this._type,document.body.appendChild(this._elt),this.initializer&&this.initializer())},o.prototype.check=function(t){do if(e.test(t.className)&&this._clsRegexp.test(t.className))break;while(t=t.parentNode);t&&t!==this._token&&(this._token=t,this.show())},o.prototype.mouseout=function(){this._token.removeEventListener("mouseout",this._mouseout,!1),this._token=null,this.hide()},o.prototype.show=function(){if(this._elt||this.init(),this._token)if(this.updater.call(this._elt,this._token.textContent)){this._token.addEventListener("mouseout",this._mouseout,!1);var e=t(this._token);this._elt.className+=" active",e.top-this._elt.offsetHeight>0?(this._elt.className=this._elt.className.replace(i,""),this._elt.style.top=e.top+"px",this._elt.style.bottom=""):(this._elt.className+=" flipped",this._elt.style.bottom=e.bottom+"px",this._elt.style.top=""),this._elt.style.left=e.left+Math.min(200,this._token.offsetWidth/2)+"px"}else this.hide()},o.prototype.hide=function(){this._elt.className=this._elt.className.replace(s,"")},o.byLanguages={},o.byType={},o.initEvents=function(t,e){var s=[];o.byLanguages[e]&&(s=s.concat(o.byLanguages[e])),o.byLanguages["*"]&&(s=s.concat(o.byLanguages["*"])),t.addEventListener("mouseover",function(t){var e=t.target;s.forEach(function(t){t.check(e)})},!1)},Prism.plugins.Previewer=o,Prism.hooks.add("after-highlight",function(t){(o.byLanguages["*"]||o.byLanguages[t.language])&&o.initEvents(t.element,t.language)})}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var e={css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(a){if(a.language&&e[a.language]&&!e[a.language].initialized){var i=e[a.language];"Array"!==Prism.util.type(i)&&(i=[i]),i.forEach(function(i){var r,l,n,s;i===!0?(r="important",l=a.language,i=a.language):(r=i.before||"important",l=i.inside||i.lang,n=i.root||Prism.languages,s=i.skip,i=a.language),!s&&Prism.languages[i]&&(Prism.languages.insertBefore(l,r,{color:/\B#(?:[0-9a-f]{3}){1,2}\b|\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B|\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGray|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGray|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGray|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gray|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGray|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGray|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGray|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i},n),a.grammar=Prism.languages[i],e[a.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("color",function(e){return this.style.backgroundColor="",this.style.backgroundColor=e,!!this.style.backgroundColor})}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var e={css:!0,less:!0,sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(i){if(i.language&&e[i.language]&&!e[i.language].initialized){var t=e[i.language];"Array"!==Prism.util.type(t)&&(t=[t]),t.forEach(function(t){var r,s,a,n;t===!0?(r=Prism.plugins.Previewer&&Prism.plugins.Previewer.byType.color?"color":"important",s=i.language,t=i.language):(r=t.before||"important",s=t.inside||t.lang,a=t.root||Prism.languages,n=t.skip,t=i.language),!n&&Prism.languages[t]&&(Prism.languages.insertBefore(s,r,{gradient:{pattern:/(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:rgb|hsl)a?\(.+?\)|[^\)])+\)/gi,inside:{"function":/[\w-]+(?=\()/,punctuation:/[(),]/}}},a),i.grammar=Prism.languages[t],e[i.language]={initialized:!0})})}});var i={},t=function(e,i,t){var r="180deg";return/^(?:-?\d*\.?\d+(?:deg|rad)|to\b|top|right|bottom|left)/.test(t[0])&&(r=t.shift(),r.indexOf("to ")<0&&(r.indexOf("top")>=0?r=r.indexOf("left")>=0?"to bottom right":r.indexOf("right")>=0?"to bottom left":"to bottom":r.indexOf("bottom")>=0?r=r.indexOf("left")>=0?"to top right":r.indexOf("right")>=0?"to top left":"to top":r.indexOf("left")>=0?r="to right":r.indexOf("right")>=0?r="to left":e&&(r.indexOf("deg")>=0?r=90-parseFloat(r)+"deg":r.indexOf("rad")>=0&&(r=Math.PI/2-parseFloat(r)+"rad")))),i+"("+r+","+t.join(",")+")"},r=function(e,i,t){if(t[0].indexOf("at")<0){var r="center",s="ellipse",a="farthest-corner";if(/\bcenter|top|right|bottom|left\b|^\d+/.test(t[0])&&(r=t.shift().replace(/\s*-?\d+(?:rad|deg)\s*/,"")),/\bcircle|ellipse|closest|farthest|contain|cover\b/.test(t[0])){var n=t.shift().split(/\s+/);!n[0]||"circle"!==n[0]&&"ellipse"!==n[0]||(s=n.shift()),n[0]&&(a=n.shift()),"cover"===a?a="farthest-corner":"contain"===a&&(a="clothest-side")}return i+"("+s+" "+a+" at "+r+","+t.join(",")+")"}return i+"("+t.join(",")+")"},s=function(e){if(i[e])return i[e];var s=e.match(/^(\b|\B-[a-z]{1,10}-)((?:repeating-)?(?:linear|radial)-gradient)/),a=s&&s[1],n=s&&s[2],l=e.replace(/^(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\(|\)$/g,"").split(/\s*,\s*/);return i[e]=n.indexOf("linear")>=0?t(a,n,l):n.indexOf("radial")>=0?r(a,n,l):n+"("+l.join(",")+")"};Prism.plugins.Previewer&&new Prism.plugins.Previewer("gradient",function(e){return this.firstChild.style.backgroundImage="",this.firstChild.style.backgroundImage=s(e),!!this.firstChild.style.backgroundImage},"*",function(){this._elt.innerHTML="
    "})}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var e={css:!0,less:!0,sass:[{lang:"sass",inside:"inside",before:"punctuation",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(r){if(r.language&&e[r.language]&&!e[r.language].initialized){var s=e[r.language];"Array"!==Prism.util.type(s)&&(s=[s]),s.forEach(function(s){var i,a,n,t;s===!0?(i="important",a=r.language,s=r.language):(i=s.before||"important",a=s.inside||s.lang,n=s.root||Prism.languages,t=s.skip,s=r.language),!t&&Prism.languages[s]&&(Prism.languages.insertBefore(a,i,{easing:/\bcubic-bezier\((?:-?\d*\.?\d+,\s*){3}-?\d*\.?\d+\)\B|\b(?:linear|ease(?:-in)?(?:-out)?)(?=\s|[;}]|$)/i},n),r.grammar=Prism.languages[s],e[r.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("easing",function(e){e={linear:"0,0,1,1",ease:".25,.1,.25,1","ease-in":".42,0,1,1","ease-out":"0,0,.58,1","ease-in-out":".42,0,.58,1"}[e]||e;var r=e.match(/-?\d*\.?\d+/g);if(4===r.length){r=r.map(function(e,r){return 100*(r%2?1-e:e)}),this.querySelector("path").setAttribute("d","M0,100 C"+r[0]+","+r[1]+", "+r[2]+","+r[3]+", 100,0");var s=this.querySelectorAll("line");return s[0].setAttribute("x2",r[0]),s[0].setAttribute("y2",r[1]),s[1].setAttribute("x2",r[2]),s[1].setAttribute("y2",r[3]),!0}return!1},"*",function(){this._elt.innerHTML=''})}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var s={css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(e){if(e.language&&s[e.language]&&!s[e.language].initialized){var a=s[e.language];"Array"!==Prism.util.type(a)&&(a=[a]),a.forEach(function(a){var i,r,n,l;a===!0?(i="important",r=e.language,a=e.language):(i=a.before||"important",r=a.inside||a.lang,n=a.root||Prism.languages,l=a.skip,a=e.language),!l&&Prism.languages[a]&&(Prism.languages.insertBefore(r,i,{time:/(?:\b|\B-|(?=\B\.))\d*\.?\d+m?s\b/i},n),e.grammar=Prism.languages[a],s[e.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("time",function(s){var e=parseFloat(s),a=s.match(/[a-z]+$/i);return e&&a?(a=a[0],this.querySelector("circle").style.animationDuration=2*e+a,!0):!1},"*",function(){this._elt.innerHTML=''})}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var a={css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]};Prism.hooks.add("before-highlight",function(s){if(s.language&&a[s.language]&&!a[s.language].initialized){var e=a[s.language];"Array"!==Prism.util.type(e)&&(e=[e]),e.forEach(function(e){var i,r,n,g;e===!0?(i="important",r=s.language,e=s.language):(i=e.before||"important",r=e.inside||e.lang,n=e.root||Prism.languages,g=e.skip,e=s.language),!g&&Prism.languages[e]&&(Prism.languages.insertBefore(r,i,{angle:/(?:\b|\B-|(?=\B\.))\d*\.?\d+(?:deg|g?rad|turn)\b/i},n),s.grammar=Prism.languages[e],a[s.language]={initialized:!0})})}}),Prism.plugins.Previewer&&new Prism.plugins.Previewer("angle",function(a){var s,e,i=parseFloat(a),r=a.match(/[a-z]+$/i);if(!i||!r)return!1;switch(r=r[0]){case"deg":s=360;break;case"grad":s=400;break;case"rad":s=2*Math.PI;break;case"turn":s=1}return e=100*i/s,e%=100,this[(0>i?"set":"remove")+"Attribute"]("data-negative",""),this.querySelector("circle").style.strokeDasharray=Math.abs(e)+",500",!0},"*",function(){this._elt.innerHTML=''})}}(); +Prism.languages["markup-templating"]={},Object.defineProperties(Prism.languages["markup-templating"],{buildPlaceholders:{value:function(e,t,n,a){e.language===t&&(e.tokenStack=[],e.code=e.code.replace(n,function(n){if("function"==typeof a&&!a(n))return n;for(var r=e.tokenStack.length;-1!==e.code.indexOf("___"+t.toUpperCase()+r+"___");)++r;return e.tokenStack[r]=n,"___"+t.toUpperCase()+r+"___"}),e.grammar=Prism.languages.markup)}},tokenizePlaceholders:{value:function(e,t){if(e.language===t&&e.tokenStack){e.grammar=Prism.languages[t];var n=0,a=Object.keys(e.tokenStack),r=function(o){if(!(n>=a.length))for(var i=0;i-1){++n;var f,u=l.substring(0,p),_=new Prism.Token(t,Prism.tokenize(s,e.grammar,t),"language-"+t,s),k=l.substring(p+("___"+t.toUpperCase()+c+"___").length);if(u||k?(f=[u,_,k].filter(function(e){return!!e}),r(f)):f=_,"string"==typeof g?Array.prototype.splice.apply(o,[i,1].concat(f)):g.content=f,n>=a.length)break}}else g.content&&"string"!=typeof g.content&&r(g.content)}};r(e.tokens)}}}}); +Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; +!function(e){e.languages.php=e.languages.extend("clike",{keyword:/\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),e.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),e.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$+(?:\w+\b|(?={))/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),e.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var n={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:n}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:n}}}),delete e.languages.php.string,e.hooks.add("before-tokenize",function(n){if(/(?:<\?php|<\?)/gi.test(n.code)){var t=/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi;e.languages["markup-templating"].buildPlaceholders(n,"php",t)}}),e.hooks.add("after-tokenize",function(n){e.languages["markup-templating"].tokenizePlaceholders(n,"php")})}(Prism); +Prism.languages.insertBefore("php","variable",{"this":/\$this\b/,global:/\$(?:_(?:SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE)|GLOBALS|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/static|self|parent/,punctuation:/::|\\/}}}); +Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},"function":/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,"boolean":/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b0x[\da-f]+\b|\b\d+\.?\d*|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"triple-quoted-string":{pattern:/("""|''')[\s\S]+?\1/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,"boolean":/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}; +!function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){n="string"==typeof n?n:e.getAttribute("data-line");for(var o,l=n.replace(/\s+/g,"").split(","),a=+e.getAttribute("data-line-offset")||0,s=r()?parseInt:parseFloat,d=s(getComputedStyle(e).lineHeight),u=t(e,"line-numbers"),c=0;o=l[c++];){var p=o.split("-"),m=+p[0],f=+p[1]||m,h=e.querySelector('.line-highlight[data-range="'+o+'"]')||document.createElement("div");if(h.setAttribute("aria-hidden","true"),h.setAttribute("data-range",o),h.className=(i||"")+" line-highlight",u&&Prism.plugins.lineNumbers){var g=Prism.plugins.lineNumbers.getLine(e,m),y=Prism.plugins.lineNumbers.getLine(e,f);g&&(h.style.top=g.offsetTop+"px"),y&&(h.style.height=y.offsetTop-g.offsetTop+y.offsetHeight+"px")}else h.setAttribute("data-start",m),f>m&&h.setAttribute("data-end",f),h.style.top=(m-a-1)*d+"px",h.textContent=new Array(f-m+2).join(" \n");u?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML=" 
     ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function l(e){var r=e.element.parentNode,a=r&&r.getAttribute("data-line");if(r&&a&&/pre/i.test(r.nodeName)){clearTimeout(o);var s=Prism.plugins.lineNumbers,d=e.plugins&&e.plugins.lineNumbers;t(r,"line-numbers")&&s&&!d?Prism.hooks.add("line-numbers",l):(n(r,a),o=setTimeout(i,1))}}),window.addEventListener("hashchange",i),window.addEventListener("resize",function(){var e=document.querySelectorAll("pre[data-line]");Array.prototype.forEach.call(e,function(e){n(e)})})}}(); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=/\n(?!$)/g,n=function(e){var n=r(e),s=n["white-space"];if("pre-wrap"===s||"pre-line"===s){var l=e.querySelector("code"),i=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),o=l.textContent.split(t);a||(a=document.createElement("span"),a.className="line-numbers-sizer",l.appendChild(a)),a.style.display="block",o.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;i.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},r=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),n)}),Prism.hooks.add("complete",function(e){if(e.code){var r=e.element.parentNode,s=/\s*\bline-numbers\b\s*/;if(r&&/pre/i.test(r.nodeName)&&(s.test(r.className)||s.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){s.test(e.element.className)&&(e.element.className=e.element.className.replace(s," ")),s.test(r.className)||(r.className+=" line-numbers");var l,i=e.code.match(t),a=i?i.length+1:1,o=new Array(a+1);o=o.join(""),l=document.createElement("span"),l.setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=o,r.hasAttribute("data-start")&&(r.style.counterReset="linenumber "+(parseInt(r.getAttribute("data-start"),10)-1)),e.element.appendChild(l),n(r),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(t,n){if("PRE"===t.tagName&&t.classList.contains(e)){var r=t.querySelector(".line-numbers-rows"),s=parseInt(t.getAttribute("data-start"),10)||1,l=s+(r.children.length-1);s>n&&(n=s),n>l&&(n=l);var i=n-s;return r.children[i]}}}}}(); +!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:=&]+(?:\?[\w\-+%~\/.:#=?&!$'()*,;]*)?(?:#[\w\-+%~\/.:#=?&!$'()*,;]*)?/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(r){r&&!r["url-link"]&&(Prism.languages.DFS(r,function(r,a,l){t.indexOf(l)>-1&&"Array"!==Prism.util.type(a)&&(a.pattern||(a=this[r]={pattern:a}),a.inside=a.inside||{},"comment"==l&&(a.inside["md-link"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},a):a.inside["url-link"]=i,a.inside["email-link"]=n)}),r["url-link"]=i,r["email-link"]=n)}},Prism.hooks.add("before-highlight",function(i){Prism.plugins.autolinker.processGrammar(i.grammar)}),Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var t=i.content.match(e);n=t[2],i.content=t[1]}i.attributes.href=n}try{i.content=decodeURIComponent(i.content)}catch(r){}})}}(); From 9eb8a73462c7ba492b7de203a6afe7abab1848c1 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 5 Sep 2018 12:28:07 +0200 Subject: [PATCH 63/79] Embed page: line-numbers --- src/Gist/Resources/views/View/embed.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index b1014b6..6f15c78 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -101,7 +101,7 @@
    -
    {{ raw_content }}
    +
    {{ raw_content }}
    From 4ee4311c1a0891a36459a8146f1a0c2111e0033f Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 11 Sep 2018 13:15:12 +0200 Subject: [PATCH 64/79] Cache remove on pages with form --- src/Gist/Controller/EditController.php | 2 ++ src/Gist/Controller/LoginController.php | 2 ++ src/Gist/Controller/MyController.php | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Gist/Controller/EditController.php b/src/Gist/Controller/EditController.php index 0eb82d6..bafdf49 100644 --- a/src/Gist/Controller/EditController.php +++ b/src/Gist/Controller/EditController.php @@ -60,6 +60,7 @@ class EditController extends Controller array( 'gist' => isset($gist) ? $gist : null, 'form' => $form->createView(), + 'no_cache' => true, ) ); } @@ -109,6 +110,7 @@ class EditController extends Controller } $viewOptions['form'] = $form->createView(); + $viewOptions['no_cache'] = true; return $this->createResponse('Edit/clone.html.twig', $viewOptions); } diff --git a/src/Gist/Controller/LoginController.php b/src/Gist/Controller/LoginController.php index 6732462..eecff06 100644 --- a/src/Gist/Controller/LoginController.php +++ b/src/Gist/Controller/LoginController.php @@ -63,6 +63,7 @@ class LoginController extends Controller 'form' => $form->createView(), 'error' => isset($error) ? $error : '', 'success' => isset($success) ? $success : '', + 'no_cache' => true, ] ); } @@ -102,6 +103,7 @@ class LoginController extends Controller [ 'form' => $form->createView(), 'error' => isset($error) ? $error : '', + 'no_cache' => true, ] ); } diff --git a/src/Gist/Controller/MyController.php b/src/Gist/Controller/MyController.php index 478ba43..b3224a5 100644 --- a/src/Gist/Controller/MyController.php +++ b/src/Gist/Controller/MyController.php @@ -63,7 +63,7 @@ class MyController extends Controller if (empty($apiKey)) { $regenerateApiKey = true; - } + } // FIXME: CSRF issue! elseif ($request->request->get('apiKey') === $apiKey && $request->request->has('generateApiKey')) { $regenerateApiKey = true; From d67ac40e3d679a048629f6fa7e260f7366a2a2b0 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 11 Sep 2018 13:22:40 +0200 Subject: [PATCH 65/79] clean-cache rule in Makefile --- Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8bf831b..bccd434 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,15 @@ GIT ?= git MKDIR ?= mkdir PHP ?= php -all: update +all: update clean-cache composer: @echo "Installing PHP dependencies" @echo "---------------------------" @echo - $(COMPOSER) install $(COMPOSER_INSTALL_FLAGS) + $(COMPOSER) install + npm: @echo "Installing CSS/JS dependencies" @echo "------------------------------" @@ -30,6 +31,13 @@ update: $(COMPOSER) update $(NPM) install +clean-cache: + @echo "Removing cache" + @echo "--------------" + @echo + + rm -fr cache/* + run: @echo "Run development server" @echo "----------------------" From 426cf0e1f1ded7bf94112685c3c95af7da72119e Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 11 Sep 2018 13:41:43 +0200 Subject: [PATCH 66/79] Fix typo in Makefile --- Makefile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index bccd434..2c7a213 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ NPM ?= npm GIT ?= git MKDIR ?= mkdir PHP ?= php +RM ?= rm all: update clean-cache @@ -11,39 +12,39 @@ composer: @echo "---------------------------" @echo - $(COMPOSER) install + ${COMPOSER} install npm: @echo "Installing CSS/JS dependencies" @echo "------------------------------" @echo - $(NPM) install + ${NPM} install update: @echo "Updating application's dependencies" @echo "-----------------------------------" @echo - $(GIT) pull origin master + ${GIT} pull origin master ${MKDIR} -p data/git ${MKDIR} -p data/cache - $(COMPOSER) update - $(NPM) install + ${COMPOSER} update + ${NPM} install clean-cache: @echo "Removing cache" @echo "--------------" @echo - rm -fr cache/* + ${RM} -fr cache/* run: @echo "Run development server" @echo "----------------------" @echo - $(PHP) -S 127.0.0.1:8080 -t web + ${PHP} -S 127.0.0.1:8080 -t web propel: @echo "Propel migration" From f6136404c9af1681cdbec1cbda155393cceccb39 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 20 Sep 2018 10:31:32 +0200 Subject: [PATCH 67/79] New language highlight: markdown --- app/locales/cn.yml | 1 + app/locales/de.yml | 1 + app/locales/en.yml | 1 + app/locales/es.yml | 1 + app/locales/fr.yml | 1 + app/locales/pl.yml | 1 + src/Gist/Form/CreateGistForm.php | 1 + src/Gist/Model/Gist.php | 1 + web/app/css/prism.css | 259 ++----------------------------- web/app/js/prism.js | 5 +- 10 files changed, 25 insertions(+), 247 deletions(-) diff --git a/app/locales/cn.yml b/app/locales/cn.yml index 1dbaee3..736aa48 100644 --- a/app/locales/cn.yml +++ b/app/locales/cn.yml @@ -98,6 +98,7 @@ form: php: 'PHP' sql: 'SQL' yaml: 'YAML' + markdown: 'MARKDOWN' perl: 'PERL' c: 'C/C++' asp: 'ASP' diff --git a/app/locales/de.yml b/app/locales/de.yml index 3461653..89f6dc0 100644 --- a/app/locales/de.yml +++ b/app/locales/de.yml @@ -98,6 +98,7 @@ form: php: 'PHP' sql: 'SQL' yaml: 'YAML' + markdown: 'MARKDOWN' perl: 'PERL' c: 'C/C++' asp: 'ASP' diff --git a/app/locales/en.yml b/app/locales/en.yml index 18fb7de..4c07af3 100644 --- a/app/locales/en.yml +++ b/app/locales/en.yml @@ -99,6 +99,7 @@ form: php: 'PHP' sql: 'SQL' yaml: 'YAML' + markdown: 'MARKDOWN' perl: 'PERL' c: 'C/C++' asp: 'ASP' diff --git a/app/locales/es.yml b/app/locales/es.yml index c315f6e..3c0f4b0 100644 --- a/app/locales/es.yml +++ b/app/locales/es.yml @@ -98,6 +98,7 @@ form: php: 'PHP' sql: 'SQL' yaml: 'YAML' + markdown: 'MARKDOWN' perl: 'PERL' c: 'C/C++' asp: 'ASP' diff --git a/app/locales/fr.yml b/app/locales/fr.yml index 8788853..d61771b 100644 --- a/app/locales/fr.yml +++ b/app/locales/fr.yml @@ -98,6 +98,7 @@ form: php: 'PHP' sql: 'SQL' yaml: 'YAML' + markdown: 'MARKDOWN' perl: 'PERL' c: 'C/C++' asp: 'ASP' diff --git a/app/locales/pl.yml b/app/locales/pl.yml index d404f11..232ce77 100644 --- a/app/locales/pl.yml +++ b/app/locales/pl.yml @@ -99,6 +99,7 @@ form: php: 'PHP' sql: 'SQL' yaml: 'YAML' + markdown: 'MARKDOWN' perl: 'PERL' c: 'C/C++' asp: 'ASP' diff --git a/src/Gist/Form/CreateGistForm.php b/src/Gist/Form/CreateGistForm.php index 060f444..3972796 100644 --- a/src/Gist/Form/CreateGistForm.php +++ b/src/Gist/Form/CreateGistForm.php @@ -97,6 +97,7 @@ class CreateGistForm extends AbstractForm 'sql' => '', 'xml' => '', 'yaml' => '', + 'markdown' => '', 'perl' => '', 'c' => '', 'asp' => '', diff --git a/src/Gist/Model/Gist.php b/src/Gist/Model/Gist.php index 54142bc..90d8259 100644 --- a/src/Gist/Model/Gist.php +++ b/src/Gist/Model/Gist.php @@ -75,6 +75,7 @@ class Gist extends BaseGist 'bash' => 'sh', 'actionscript3' => 'as', 'text' => 'txt', + 'markdown' => 'md', ); return str_replace(array_keys($data), array_values($data), $this->getType()); diff --git a/web/app/css/prism.css b/web/app/css/prism.css index 5199180..2c180a4 100644 --- a/web/app/css/prism.css +++ b/web/app/css/prism.css @@ -1,4 +1,5 @@ -/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+actionscript+c+aspnet+bash+cpp+csharp+css-extras+diff+perl+php+php-extras+python+sql+yaml&plugins=line-highlight+line-numbers+autolinker+previewer-base+previewer-color+previewer-gradient+previewer-easing+previewer-time+previewer-angle */ +/* 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+autolinker */ /** * prism.js default theme for JavaScript, CSS and HTML * Based on dabblet (http://dabblet.com) @@ -105,7 +106,7 @@ pre[class*="language-"] { .token.url, .language-css .token.string, .style .token.string { - color: #a67f59; + color: #9a6e3a; background: hsla(0, 0%, 100%, .5); } @@ -115,7 +116,8 @@ pre[class*="language-"] { color: #07a; } -.token.function { +.token.function, +.token.class-name { color: #DD4A68; } @@ -182,15 +184,20 @@ pre[data-line] { bottom: .4em; } -pre.line-numbers { +.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.line-numbers > code { +pre[class*="language-"].line-numbers > code { position: relative; - white-space: inherit; + white-space: inherit; } .line-numbers .line-numbers-rows { @@ -223,245 +230,7 @@ pre.line-numbers > code { padding-right: 0.8em; text-align: right; } + .token a { color: inherit; } -.prism-previewer, -.prism-previewer:before, -.prism-previewer:after { - position: absolute; - pointer-events: none; -} -.prism-previewer, -.prism-previewer:after { - left: 50%; -} -.prism-previewer { - margin-top: -48px; - width: 32px; - height: 32px; - margin-left: -16px; - - opacity: 0; - -webkit-transition: opacity .25s; - -o-transition: opacity .25s; - transition: opacity .25s; -} -.prism-previewer.flipped { - margin-top: 0; - margin-bottom: -48px; -} -.prism-previewer:before, -.prism-previewer:after { - content: ''; - position: absolute; - pointer-events: none; -} -.prism-previewer:before { - top: -5px; - right: -5px; - left: -5px; - bottom: -5px; - border-radius: 10px; - border: 5px solid #fff; - box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75); -} - -.prism-previewer:after { - top: 100%; - width: 0; - height: 0; - margin: 5px 0 0 -7px; - border: 7px solid transparent; - border-color: rgba(255, 0, 0, 0); - border-top-color: #fff; -} -.prism-previewer.flipped:after { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: 5px; - border-top-color: rgba(255, 0, 0, 0); - border-bottom-color: #fff; -} -.prism-previewer.active { - opacity: 1; -} -.prism-previewer-color { - background-image: linear-gradient(45deg, #bbb 25%, transparent 25%, transparent 75%, #bbb 75%, #bbb), linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb); - background-size: 10px 10px; - background-position: 0 0, 5px 5px; -} -.prism-previewer-color:before { - background-color: inherit; - background-clip: padding-box; -} - -.prism-previewer-gradient { - background-image: linear-gradient(45deg, #bbb 25%, transparent 25%, transparent 75%, #bbb 75%, #bbb), linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb); - background-size: 10px 10px; - background-position: 0 0, 5px 5px; - - width: 64px; - margin-left: -32px; -} -.prism-previewer-gradient:before { - content: none; -} -.prism-previewer-gradient div { - position: absolute; - top: -5px; - left: -5px; - right: -5px; - bottom: -5px; - border-radius: 10px; - border: 5px solid #fff; - box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75); -} -.prism-previewer-easing { - margin-top: -76px; - margin-left: -30px; - width: 60px; - height: 60px; - background: #333; -} -.prism-previewer-easing.flipped { - margin-bottom: -116px; -} -.prism-previewer-easing svg { - width: 60px; - height: 60px; -} -.prism-previewer-easing circle { - fill: hsl(200, 10%, 20%); - stroke: white; -} -.prism-previewer-easing path { - fill: none; - stroke: white; - stroke-linecap: round; - stroke-width: 4; -} -.prism-previewer-easing line { - stroke: white; - stroke-opacity: 0.5; - stroke-width: 2; -} -@-webkit-keyframes prism-previewer-time { - 0% { - stroke-dasharray: 0, 500; - stroke-dashoffset: 0; - } - 50% { - stroke-dasharray: 100, 500; - stroke-dashoffset: 0; - } - 100% { - stroke-dasharray: 0, 500; - stroke-dashoffset: -100; - } -} - -@-o-keyframes prism-previewer-time { - 0% { - stroke-dasharray: 0, 500; - stroke-dashoffset: 0; - } - 50% { - stroke-dasharray: 100, 500; - stroke-dashoffset: 0; - } - 100% { - stroke-dasharray: 0, 500; - stroke-dashoffset: -100; - } -} - -@-moz-keyframes prism-previewer-time { - 0% { - stroke-dasharray: 0, 500; - stroke-dashoffset: 0; - } - 50% { - stroke-dasharray: 100, 500; - stroke-dashoffset: 0; - } - 100% { - stroke-dasharray: 0, 500; - stroke-dashoffset: -100; - } -} - -@keyframes prism-previewer-time { - 0% { - stroke-dasharray: 0, 500; - stroke-dashoffset: 0; - } - 50% { - stroke-dasharray: 100, 500; - stroke-dashoffset: 0; - } - 100% { - stroke-dasharray: 0, 500; - stroke-dashoffset: -100; - } -} - -.prism-previewer-time:before { - border-radius: 50%; - background: #fff; -} -.prism-previewer-time:after { - margin-top: 4px; -} -.prism-previewer-time svg { - width: 32px; - height: 32px; - -webkit-transform: rotate(-90deg); - -moz-transform: rotate(-90deg); - -ms-transform: rotate(-90deg); - -o-transform: rotate(-90deg); - transform: rotate(-90deg); -} -.prism-previewer-time circle { - fill: transparent; - stroke: hsl(200, 10%, 20%); - stroke-opacity: 0.9; - stroke-width: 32; - stroke-dasharray: 0, 500; - stroke-dashoffset: 0; - -webkit-animation: prism-previewer-time linear infinite 3s; - -moz-animation: prism-previewer-time linear infinite 3s; - -o-animation: prism-previewer-time linear infinite 3s; - animation: prism-previewer-time linear infinite 3s; -} -.prism-previewer-angle:before { - border-radius: 50%; - background: #fff; -} -.prism-previewer-angle:after { - margin-top: 4px; -} -.prism-previewer-angle svg { - width: 32px; - height: 32px; - -webkit-transform: rotate(-90deg); - -moz-transform: rotate(-90deg); - -ms-transform: rotate(-90deg); - -o-transform: rotate(-90deg); - transform: rotate(-90deg); -} -.prism-previewer-angle[data-negative] svg { - -webkit-transform: scaleX(-1) rotate(-90deg); - -moz-transform: scaleX(-1) rotate(-90deg); - -ms-transform: scaleX(-1) rotate(-90deg); - -o-transform: scaleX(-1) rotate(-90deg); - transform: scaleX(-1) rotate(-90deg); -} -.prism-previewer-angle circle { - fill: transparent; - stroke: hsl(200, 10%, 20%); - stroke-opacity: 0.9; - stroke-width: 32; - stroke-dasharray: 0, 500; -} diff --git a/web/app/js/prism.js b/web/app/js/prism.js index ffc8935..35e67ce 100644 --- a/web/app/js/prism.js +++ b/web/app/js/prism.js @@ -1,9 +1,9 @@ /* 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+perl+php+php-extras+sql+python+yaml&plugins=line-highlight+line-numbers+autolinker */ +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+autolinker */ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-([\w-]+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){if(m&&b!=t.length-1){h.lastIndex=k;var _=h.exec(e);if(!_)break;for(var j=_.index+(d?_[1].length:0),P=_.index+_[0].length,A=b,x=k,O=t.length;O>A&&(P>x||!t[A].type&&!t[A-1].greedy);++A)x+=t[A].length,j>=x&&(++b,k=x);if(t[b]instanceof s)continue;I=A-b,w=e.slice(k,x),_.index-=k}else{h.lastIndex=0;var _=h.exec(w),I=1}if(_){d&&(p=_[1]?_[1].length:0);var j=_.index+p,_=_[0].slice(p),P=j+_.length,N=w.slice(0,j),S=w.slice(P),C=[b,I];N&&(++b,k+=N.length,C.push(N));var E=new s(u,f?n.tokenize(_,f):_,y,_,m);if(C.push(E),S&&C.push(S),Array.prototype.splice.apply(t,C),1!=I&&n.matchGrammar(e,t,r,b,k,!0,u),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css",greedy:!0}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); -Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/],number:/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"},constant:/\b[A-Z][A-Z\d_]*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:Prism.languages.markup}}}); Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?/,number:/(?:\b0x[\da-f]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; @@ -14,6 +14,7 @@ Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive tag":{pa Prism.languages.css.selector={pattern:/[^{}\s][^{}]*(?=\s*\{)/,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%.]+/}); Prism.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d+.*$/m],deleted:/^[-<].*$/m,inserted:/^[+>].*$/m,diff:{pattern:/^!(?!!).+$/m,alias:"important"}}; Prism.languages["markup-templating"]={},Object.defineProperties(Prism.languages["markup-templating"],{buildPlaceholders:{value:function(e,t,n,a){e.language===t&&(e.tokenStack=[],e.code=e.code.replace(n,function(n){if("function"==typeof a&&!a(n))return n;for(var r=e.tokenStack.length;-1!==e.code.indexOf("___"+t.toUpperCase()+r+"___");)++r;return e.tokenStack[r]=n,"___"+t.toUpperCase()+r+"___"}),e.grammar=Prism.languages.markup)}},tokenizePlaceholders:{value:function(e,t){if(e.language===t&&e.tokenStack){e.grammar=Prism.languages[t];var n=0,a=Object.keys(e.tokenStack),r=function(o){if(!(n>=a.length))for(var i=0;i-1){++n;var f,u=l.substring(0,p),_=new Prism.Token(t,Prism.tokenize(s,e.grammar,t),"language-"+t,s),k=l.substring(p+("___"+t.toUpperCase()+c+"___").length);if(u||k?(f=[u,_,k].filter(function(e){return!!e}),r(f)):f=_,"string"==typeof g?Array.prototype.splice.apply(o,[i,1].concat(f)):g.content=f,n>=a.length)break}}else g.content&&"string"!=typeof g.content&&r(g.content)}};r(e.tokens)}}}}); +Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.italic.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.bold.inside.italic=Prism.languages.markdown.italic,Prism.languages.markdown.italic.inside.bold=Prism.languages.markdown.bold; Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; !function(e){e.languages.php=e.languages.extend("clike",{keyword:/\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),e.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),e.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$+(?:\w+\b|(?={))/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),e.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var n={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:n}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:n}}}),delete e.languages.php.string,e.hooks.add("before-tokenize",function(n){if(/(?:<\?php|<\?)/gi.test(n.code)){var t=/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi;e.languages["markup-templating"].buildPlaceholders(n,"php",t)}}),e.hooks.add("after-tokenize",function(n){e.languages["markup-templating"].tokenizePlaceholders(n,"php")})}(Prism); Prism.languages.insertBefore("php","variable",{"this":/\$this\b/,global:/\$(?:_(?:SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE)|GLOBALS|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/static|self|parent/,punctuation:/::|\\/}}}); From faab3c4252b8600546f19699801c5c320dc531fd Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 9 Oct 2018 16:36:38 +0200 Subject: [PATCH 68/79] API link updated --- app/locales/cn.yml | 2 +- app/locales/de.yml | 2 +- app/locales/en.yml | 2 +- app/locales/es.yml | 2 +- app/locales/fr.yml | 2 +- app/locales/pl.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/locales/cn.yml b/app/locales/cn.yml index 736aa48..c2adf88 100644 --- a/app/locales/cn.yml +++ b/app/locales/cn.yml @@ -44,7 +44,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Powered by GIST, it''s open source :) - API

    ' + text: '

    Powered by GIST, it''s open source :) - API

    ' login: login: diff --git a/app/locales/de.yml b/app/locales/de.yml index 89f6dc0..656f71f 100644 --- a/app/locales/de.yml +++ b/app/locales/de.yml @@ -44,7 +44,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Powered by GIST, it''s open source :) - API

    ' + text: '

    Powered by GIST, it''s open source :) - API

    ' login: login: diff --git a/app/locales/en.yml b/app/locales/en.yml index 4c07af3..40e7454 100644 --- a/app/locales/en.yml +++ b/app/locales/en.yml @@ -45,7 +45,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Powered by GIST, it''s open source :) - API

    ' + text: '

    Powered by GIST, it''s open source :) - API

    ' login: login: diff --git a/app/locales/es.yml b/app/locales/es.yml index 3c0f4b0..83c0078 100644 --- a/app/locales/es.yml +++ b/app/locales/es.yml @@ -44,7 +44,7 @@ date: format: 'd/m/Y H\hi s\s' footer: - text: '

    Impulsado por GIST, es libre :) - API

    ' + text: '

    Impulsado por GIST, es libre :) - API

    ' login: login: diff --git a/app/locales/fr.yml b/app/locales/fr.yml index d61771b..63c79ac 100644 --- a/app/locales/fr.yml +++ b/app/locales/fr.yml @@ -44,7 +44,7 @@ date: format: 'd/m/Y H\hi s\s' footer: - text: '

    Propulsé par GIST, c''est libre :) - API

    ' + text: '

    Propulsé par GIST, c''est libre :) - API

    ' login: login: diff --git a/app/locales/pl.yml b/app/locales/pl.yml index 232ce77..4eaf452 100644 --- a/app/locales/pl.yml +++ b/app/locales/pl.yml @@ -45,7 +45,7 @@ date: format: 'Y-m-d h:i:s' footer: - text: '

    Napędzane przez GIST, to jest open source :) - API

    ' + text: '

    Napędzane przez GIST, to jest open source :) - API

    ' login: login: From f2e30bbd8fb06ebcc9ed4bd2991ad48d43c1b68e Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 21 Oct 2018 15:38:57 +0200 Subject: [PATCH 69/79] Issue template --- ISSUE_TEMPLATE.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..f61d999 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,24 @@ +## Environment + +* GIST version or GIT commit: +* PHP Version: ... +* GIT version. ... +* HTTPD (Nginx, Apache2): +* DBMS (MySQL, SQLite, PostgreSQL): + + +## Description: + +... + +### Steps to reproduce + +#### Observed Results: + +1. ... +2. ... +3. ... + +#### Expected Results: + +... From a8a3eadc710e01d50f255844528e24519978391a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 21 Oct 2018 15:43:10 +0200 Subject: [PATCH 70/79] Issue template --- ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index f61d999..2c87740 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -3,8 +3,8 @@ * GIST version or GIT commit: * PHP Version: ... * GIT version. ... -* HTTPD (Nginx, Apache2): -* DBMS (MySQL, SQLite, PostgreSQL): +* HTTPD (Nginx, Apache2): ... +* DBMS (MySQL, SQLite, PostgreSQL): ... ## Description: From 0ff9d4a5269a6a13b2d2b98495aa9cf70c880efe Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 21 Oct 2018 15:45:08 +0200 Subject: [PATCH 71/79] Issue template --- ISSUE_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 2c87740..5fcba4f 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,24 +1,24 @@ ## Environment -* GIST version or GIT commit: +* GIST version or GIT commit: ... * PHP Version: ... * GIT version. ... * HTTPD (Nginx, Apache2): ... * DBMS (MySQL, SQLite, PostgreSQL): ... -## Description: +## Description ... ### Steps to reproduce -#### Observed Results: +#### Observed Results 1. ... 2. ... 3. ... -#### Expected Results: +#### Expected Results ... From 3972513905bcb007c8dbf56bb5dff40774df33c8 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 21 Oct 2018 15:48:14 +0200 Subject: [PATCH 72/79] Issue template --- ISSUE_TEMPLATE.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 5fcba4f..8d29688 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -13,12 +13,14 @@ ### Steps to reproduce -#### Observed Results - 1. ... 2. ... 3. ... +#### Observed Results + +... + #### Expected Results ... From 719560908645183def3752b0f8f15637cd04e32e Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 3 Jan 2019 14:52:44 +0100 Subject: [PATCH 73/79] Fix #15: autolinker plugin removed --- web/app/css/prism.css | 5 +---- web/app/js/prism.js | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/web/app/css/prism.css b/web/app/css/prism.css index 2c180a4..330bdc9 100644 --- a/web/app/css/prism.css +++ b/web/app/css/prism.css @@ -1,5 +1,5 @@ /* 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+autolinker */ +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) @@ -231,6 +231,3 @@ pre[class*="language-"].line-numbers > code { text-align: right; } -.token a { - color: inherit; -} diff --git a/web/app/js/prism.js b/web/app/js/prism.js index 35e67ce..c8c20ca 100644 --- a/web/app/js/prism.js +++ b/web/app/js/prism.js @@ -1,26 +1,25 @@ /* 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+autolinker */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-([\w-]+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){if(m&&b!=t.length-1){h.lastIndex=k;var _=h.exec(e);if(!_)break;for(var j=_.index+(d?_[1].length:0),P=_.index+_[0].length,A=b,x=k,O=t.length;O>A&&(P>x||!t[A].type&&!t[A-1].greedy);++A)x+=t[A].length,j>=x&&(++b,k=x);if(t[b]instanceof s)continue;I=A-b,w=e.slice(k,x),_.index-=k}else{h.lastIndex=0;var _=h.exec(w),I=1}if(_){d&&(p=_[1]?_[1].length:0);var j=_.index+p,_=_[0].slice(p),P=j+_.length,N=w.slice(0,j),S=w.slice(P),C=[b,I];N&&(++b,k+=N.length,C.push(N));var E=new s(u,f?n.tokenize(_,f):_,y,_,m);if(C.push(E),S&&C.push(S),Array.prototype.splice.apply(t,C),1!=I&&n.matchGrammar(e,t,r,b,k,!0,u),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +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 */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-([\w-]+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){if(m&&b!=t.length-1){h.lastIndex=k;var _=h.exec(e);if(!_)break;for(var j=_.index+(d?_[1].length:0),P=_.index+_[0].length,A=b,x=k,O=t.length;O>A&&(P>x||!t[A].type&&!t[A-1].greedy);++A)x+=t[A].length,j>=x&&(++b,k=x);if(t[b]instanceof s)continue;I=A-b,w=e.slice(k,x),_.index-=k}else{h.lastIndex=0;var _=h.exec(w),I=1}if(_){d&&(p=_[1]?_[1].length:0);var j=_.index+p,_=_[0].slice(p),P=j+_.length,N=w.slice(0,j),S=w.slice(P),C=[b,I];N&&(++b,k+=N.length,C.push(N));var E=new s(u,f?n.tokenize(_,f):_,y,_,m);if(C.push(E),S&&C.push(S),Array.prototype.splice.apply(t,C),1!=I&&n.matchGrammar(e,t,a,b,k,!0,u),i)break}else if(i)break}}}}},tokenize:function(e,t){var a=[e],r=t.rest;if(r){for(var l in r)t[l]=r[l];delete t.rest}return n.matchGrammar(e,a,t,0,0,!1),a},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var l={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,l=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; -Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css",greedy:!0}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); +Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?[\s\S]*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css",greedy:!0}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/],number:/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"},constant:/\b[A-Z][A-Z\d_]*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},/\b(?:as|async|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/],number:/\b(?:(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+)n?|\d+n|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,"function":/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\(|\.(?:apply|bind|call)\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)[^\s()][^()]*?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/,inside:Prism.languages.javascript},{pattern:/(\(\s*)[^\s()][^()]*?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)[^\s()][^()]*?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z][A-Z\d_]*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${[^}]+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:Prism.languages.markup}}}); Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?/,number:/(?:\b0x[\da-f]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; -Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/,string:[{pattern:/@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/,greedy:!0}],"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=\s+\w+)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|interface|new)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)f?/i}),Prism.languages.insertBefore("csharp","class-name",{"generic-method":{pattern:/\w+\s*<[^>\r\n]+?>\s*(?=\()/,inside:{"function":/^\w+/,"class-name":{pattern:/\b[A-Z]\w*(?:\.\w+)*\b/,inside:{punctuation:/\./}},keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.dotnet=Prism.languages.csharp; -!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[\w#?*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)["']?(\w+?)["']?\s*\r?\n(?:[\s\S])*?\r?\n\2/,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|[\s;|&])(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|[\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&])(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\s;|&])/,lookbehind:!0},"boolean":{pattern:/(^|[\s;|&])(?:true|false)(?=$|[\s;|&])/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a.string=e.languages.bash.string,a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a["boolean"]=e.languages.bash["boolean"],a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation,e.languages.shell=e.languages.bash}(Prism); +Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/,string:[{pattern:/@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/,greedy:!0}],"class-name":[{pattern:/\b[A-Z]\w*(?:\.\w+)*\b(?=\s+\w+)/,inside:{punctuation:/\./}},{pattern:/(\[)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/(\b(?:class|interface)\s+[A-Z]\w*(?:\.\w+)*\s*:\s*)[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}},{pattern:/((?:\b(?:class|interface|new)\s+)|(?:catch\s+\())[A-Z]\w*(?:\.\w+)*\b/,lookbehind:!0,inside:{punctuation:/\./}}],number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)f?/i,operator:/>>=?|<<=?|[-=]>|([-+&|?])\1|~|[-+*\/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),Prism.languages.insertBefore("csharp","class-name",{"generic-method":{pattern:/\w+\s*<[^>\r\n]+?>\s*(?=\()/,inside:{"function":/^\w+/,"class-name":{pattern:/\b[A-Z]\w*(?:\.\w+)*\b/,inside:{punctuation:/\./}},keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.dotnet=Prism.languages.csharp; +!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[\w#?*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)["']?(\w+?)["']?\s*\r?\n(?:[\s\S])*?\r?\n\2/,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|[\s;|&])(?:alias|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|hash|head|help|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logout|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tail|tar|tee|test|time|timeout|times|top|touch|tr|traceroute|trap|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip|zypper)(?=$|[\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&])(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\s;|&])/,lookbehind:!0},"boolean":{pattern:/(^|[\s;|&])(?:true|false)(?=$|[\s;|&])/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a.string=e.languages.bash.string,a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a["boolean"]=e.languages.bash["boolean"],a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation,e.languages.shell=e.languages.bash}(Prism); Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(?:true|false)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)\w+/i,lookbehind:!0}}),Prism.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}); Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive tag":{pattern:/<%\s*@.*%>/i,inside:{"page-directive tag":/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,rest:Prism.languages.markup.tag.inside}},"directive tag":{pattern:/<%.*%>/i,inside:{"directive tag":/<%\s*?[$=%#:]{0,2}|%>/i,rest:Prism.languages.csharp}}}),Prism.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("inside","punctuation",{"directive tag":Prism.languages.aspnet["directive tag"]},Prism.languages.aspnet.tag.inside["attr-value"]),Prism.languages.insertBefore("aspnet","comment",{"asp comment":/<%--[\s\S]*?--%>/}),Prism.languages.insertBefore("aspnet",Prism.languages.javascript?"script":"tag",{"asp script":{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.csharp||{}}}); -Prism.languages.css.selector={pattern:/[^{}\s][^{}]*(?=\s*\{)/,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","function",{hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,number:/[\d%.]+/}); +Prism.languages.css.selector={pattern:Prism.languages.css.selector,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+(?:\(.*\))?/,"class":/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:/\[[^\]]+\]/}},Prism.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),Prism.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,unit:{pattern:/(\d)(?:%|[a-z]+)/,lookbehind:!0},number:/-?[\d.]+/}); Prism.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d+.*$/m],deleted:/^[-<].*$/m,inserted:/^[+>].*$/m,diff:{pattern:/^!(?!!).+$/m,alias:"important"}}; Prism.languages["markup-templating"]={},Object.defineProperties(Prism.languages["markup-templating"],{buildPlaceholders:{value:function(e,t,n,a){e.language===t&&(e.tokenStack=[],e.code=e.code.replace(n,function(n){if("function"==typeof a&&!a(n))return n;for(var r=e.tokenStack.length;-1!==e.code.indexOf("___"+t.toUpperCase()+r+"___");)++r;return e.tokenStack[r]=n,"___"+t.toUpperCase()+r+"___"}),e.grammar=Prism.languages.markup)}},tokenizePlaceholders:{value:function(e,t){if(e.language===t&&e.tokenStack){e.grammar=Prism.languages[t];var n=0,a=Object.keys(e.tokenStack),r=function(o){if(!(n>=a.length))for(var i=0;i-1){++n;var f,u=l.substring(0,p),_=new Prism.Token(t,Prism.tokenize(s,e.grammar,t),"language-"+t,s),k=l.substring(p+("___"+t.toUpperCase()+c+"___").length);if(u||k?(f=[u,_,k].filter(function(e){return!!e}),r(f)):f=_,"string"==typeof g?Array.prototype.splice.apply(o,[i,1].concat(f)):g.content=f,n>=a.length)break}}else g.content&&"string"!=typeof g.content&&r(g.content)}};r(e.tokens)}}}}); -Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.italic.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.bold.inside.italic=Prism.languages.markdown.italic,Prism.languages.markdown.italic.inside.bold=Prism.languages.markdown.bold; +Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\r?\n|\r))[\s\S]+?(?=(?:\r?\n|\r)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,greedy:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,greedy:!0,inside:{punctuation:/^[*_]|[*_]$/}},strike:{pattern:/(^|[^\\])(~~?)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,greedy:!0,inside:{punctuation:/^~~?|~~?$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.italic.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.strike.inside.url=Prism.languages.markdown.url,Prism.languages.markdown.bold.inside.italic=Prism.languages.markdown.italic,Prism.languages.markdown.bold.inside.strike=Prism.languages.markdown.strike,Prism.languages.markdown.italic.inside.bold=Prism.languages.markdown.bold,Prism.languages.markdown.italic.inside.strike=Prism.languages.markdown.strike,Prism.languages.markdown.strike.inside.bold=Prism.languages.markdown.bold,Prism.languages.markdown.strike.inside.italic=Prism.languages.markdown.italic,Prism.hooks.add("after-tokenize",function(a){function n(a){if(a&&"string"!=typeof a)for(var e=0,i=a.length;i>e;e++){var r=a[e];if("code"===r.type){var t=r.content[1],s=r.content[3];if(t&&s&&"code-language"===t.type&&"code-block"===s.type&&"string"==typeof t.content){var o="language-"+t.content.trim().split(/\s+/)[0].toLowerCase();s.alias?"string"==typeof s.alias?s.alias=[s.alias,o]:s.alias.push(o):s.alias=[o]}}else n(r.content)}}"markdown"===a.language&&n(a.tokens)}),Prism.hooks.add("wrap",function(a){if("code-block"===a.type){for(var n="",e=0,i=a.classes.length;i>e;e++){var r=a.classes[e],t=/language-(\w+)/.exec(r);if(t){n=t[1];break}}var s=Prism.languages[n];if(s){var o=a.content.replace(/</g,"<").replace(/&/g,"&");a.content=Prism.highlight(o,s,n)}}}),Prism.languages.md=Prism.languages.markdown; Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; -!function(e){e.languages.php=e.languages.extend("clike",{keyword:/\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),e.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),e.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$+(?:\w+\b|(?={))/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),e.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var n={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:n}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:n}}}),delete e.languages.php.string,e.hooks.add("before-tokenize",function(n){if(/(?:<\?php|<\?)/gi.test(n.code)){var t=/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi;e.languages["markup-templating"].buildPlaceholders(n,"php",t)}}),e.hooks.add("after-tokenize",function(n){e.languages["markup-templating"].tokenizePlaceholders(n,"php")})}(Prism); +!function(e){e.languages.php=e.languages.extend("clike",{keyword:/\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z_][A-Z0-9_]*\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),e.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),e.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$+(?:\w+\b|(?={))/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),e.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var n={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:n}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:n}}}),delete e.languages.php.string,e.hooks.add("before-tokenize",function(n){if(/(?:<\?php|<\?)/gi.test(n.code)){var t=/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi;e.languages["markup-templating"].buildPlaceholders(n,"php",t)}}),e.hooks.add("after-tokenize",function(n){e.languages["markup-templating"].tokenizePlaceholders(n,"php")})}(Prism); Prism.languages.insertBefore("php","variable",{"this":/\$this\b/,global:/\$(?:_(?:SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE)|GLOBALS|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/static|self|parent/,punctuation:/::|\\/}}}); Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},"function":/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,"boolean":/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b0x[\da-f]+\b|\b\d+\.?\d*|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"triple-quoted-string":{pattern:/("""|''')[\s\S]+?\1/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,"boolean":/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}; +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]+?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^\s*)@\w+(?:\.\w+)*/i,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,"boolean":/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}|\s*#))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},Prism.languages.yml=Prism.languages.yaml; !function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){n="string"==typeof n?n:e.getAttribute("data-line");for(var o,l=n.replace(/\s+/g,"").split(","),a=+e.getAttribute("data-line-offset")||0,s=r()?parseInt:parseFloat,d=s(getComputedStyle(e).lineHeight),u=t(e,"line-numbers"),c=0;o=l[c++];){var p=o.split("-"),m=+p[0],f=+p[1]||m,h=e.querySelector('.line-highlight[data-range="'+o+'"]')||document.createElement("div");if(h.setAttribute("aria-hidden","true"),h.setAttribute("data-range",o),h.className=(i||"")+" line-highlight",u&&Prism.plugins.lineNumbers){var g=Prism.plugins.lineNumbers.getLine(e,m),y=Prism.plugins.lineNumbers.getLine(e,f);g&&(h.style.top=g.offsetTop+"px"),y&&(h.style.height=y.offsetTop-g.offsetTop+y.offsetHeight+"px")}else h.setAttribute("data-start",m),f>m&&h.setAttribute("data-end",f),h.style.top=(m-a-1)*d+"px",h.textContent=new Array(f-m+2).join(" \n");u?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML=" 
     ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function l(e){var r=e.element.parentNode,a=r&&r.getAttribute("data-line");if(r&&a&&/pre/i.test(r.nodeName)){clearTimeout(o);var s=Prism.plugins.lineNumbers,d=e.plugins&&e.plugins.lineNumbers;t(r,"line-numbers")&&s&&!d?Prism.hooks.add("line-numbers",l):(n(r,a),o=setTimeout(i,1))}}),window.addEventListener("hashchange",i),window.addEventListener("resize",function(){var e=document.querySelectorAll("pre[data-line]");Array.prototype.forEach.call(e,function(e){n(e)})})}}(); !function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=/\n(?!$)/g,n=function(e){var n=r(e),s=n["white-space"];if("pre-wrap"===s||"pre-line"===s){var l=e.querySelector("code"),i=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),o=l.textContent.split(t);a||(a=document.createElement("span"),a.className="line-numbers-sizer",l.appendChild(a)),a.style.display="block",o.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;i.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},r=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),n)}),Prism.hooks.add("complete",function(e){if(e.code){var r=e.element.parentNode,s=/\s*\bline-numbers\b\s*/;if(r&&/pre/i.test(r.nodeName)&&(s.test(r.className)||s.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){s.test(e.element.className)&&(e.element.className=e.element.className.replace(s," ")),s.test(r.className)||(r.className+=" line-numbers");var l,i=e.code.match(t),a=i?i.length+1:1,o=new Array(a+1);o=o.join(""),l=document.createElement("span"),l.setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=o,r.hasAttribute("data-start")&&(r.style.counterReset="linenumber "+(parseInt(r.getAttribute("data-start"),10)-1)),e.element.appendChild(l),n(r),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(t,n){if("PRE"===t.tagName&&t.classList.contains(e)){var r=t.querySelector(".line-numbers-rows"),s=parseInt(t.getAttribute("data-start"),10)||1,l=s+(r.children.length-1);s>n&&(n=s),n>l&&(n=l);var i=n-s;return r.children[i]}}}}}(); -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:=&]+(?:\?[\w\-+%~\/.:#=?&!$'()*,;]*)?(?:#[\w\-+%~\/.:#=?&!$'()*,;]*)?/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(r){r&&!r["url-link"]&&(Prism.languages.DFS(r,function(r,a,l){t.indexOf(l)>-1&&"Array"!==Prism.util.type(a)&&(a.pattern||(a=this[r]={pattern:a}),a.inside=a.inside||{},"comment"==l&&(a.inside["md-link"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},a):a.inside["url-link"]=i,a.inside["email-link"]=n)}),r["url-link"]=i,r["email-link"]=n)}},Prism.hooks.add("before-highlight",function(i){Prism.plugins.autolinker.processGrammar(i.grammar)}),Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var t=i.content.match(e);n=t[2],i.content=t[1]}i.attributes.href=n}try{i.content=decodeURIComponent(i.content)}catch(r){}})}}(); From 7c322346267fcdf501491bb3fca4a5475edd2c97 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 7 Feb 2019 10:26:42 +0100 Subject: [PATCH 74/79] add cache controle using createResponse on embedJs action --- src/Gist/Controller/ViewController.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index d3be5bd..667cb3b 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -72,13 +72,10 @@ class ViewController extends Controller { $viewOptions = $this->getViewOptions($request, $gist, $commit); - return new Response( - $this->render('View/embedJs.html.twig', $viewOptions), - 200, - array( - 'Content-Type' => 'text/javascript', - ) - ); + $response = $this->createResponse('View/embedJs.html.twig', $viewOptions), + $response->headers->set('Content-Type', 'text/javascript'); + + return $response; } /** From e5f996705eae745f4973f33458deb8c7ae9dfe8d Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 7 Feb 2019 10:27:37 +0100 Subject: [PATCH 75/79] add cache controle using createResponse on embedJs action --- src/Gist/Controller/ViewController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index 667cb3b..e878902 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -72,7 +72,7 @@ class ViewController extends Controller { $viewOptions = $this->getViewOptions($request, $gist, $commit); - $response = $this->createResponse('View/embedJs.html.twig', $viewOptions), + $response = $this->createResponse('View/embedJs.html.twig', $viewOptions); $response->headers->set('Content-Type', 'text/javascript'); return $response; From 6d84cf319c5de07e736636517aebec187a5f6b23 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 13 Mar 2019 11:36:19 +0100 Subject: [PATCH 76/79] remove cache on view page --- src/Gist/Controller/ViewController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index e878902..efbce98 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -31,6 +31,8 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); if (is_array($viewOptions)) { + $viewOptions['no_cache'] = true; + return $this->createResponse('View/view.html.twig', $viewOptions); } else { return $this->notFoundResponse(); From cb286ce7048779f97246af8d70d6e516c05b0b8a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 25 Apr 2019 15:59:26 +0200 Subject: [PATCH 77/79] fix issue #4 --- src/Gist/Controller/Controller.php | 22 +++++++++ src/Gist/Controller/ViewController.php | 27 ++++++++++ src/Gist/Resources/views/View/embed.html.twig | 22 ++++++--- .../Resources/views/View/embedJs.html.twig | 10 +++- src/Gist/Resources/views/View/view.html.twig | 49 ++++++++++++++++--- 5 files changed, 112 insertions(+), 18 deletions(-) diff --git a/src/Gist/Controller/Controller.php b/src/Gist/Controller/Controller.php index 6babb1c..c13fd38 100644 --- a/src/Gist/Controller/Controller.php +++ b/src/Gist/Controller/Controller.php @@ -20,6 +20,27 @@ abstract class Controller */ protected $app; + /** + * @var array + */ + protected $types = [ + 'html', + 'css', + 'javascript', + 'php', + 'sql', + 'xml', + 'yaml', + 'markdown', + 'perl', + 'c', + 'asp', + 'python', + 'bash', + 'actionscript3', + 'text', + ]; + /** * __construct. * @@ -88,6 +109,7 @@ abstract class Controller return array( 'gist' => $gist, 'type' => $gist->getType(), + 'types' => $this->types, 'history' => $history, 'commit' => $commit, 'raw_content' => $content, diff --git a/src/Gist/Controller/ViewController.php b/src/Gist/Controller/ViewController.php index efbce98..8ea5002 100644 --- a/src/Gist/Controller/ViewController.php +++ b/src/Gist/Controller/ViewController.php @@ -31,6 +31,15 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); if (is_array($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); @@ -55,6 +64,15 @@ class ViewController extends Controller $viewOptions = $this->getViewOptions($request, $gist, $commit); if (is_array($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 { return $this->notFoundResponse(); @@ -74,6 +92,15 @@ class ViewController extends Controller { $viewOptions = $this->getViewOptions($request, $gist, $commit); + if ($request->query->has('type')) { + $type = $request->query->get('type'); + + if (in_array($type, $this->types)) { + $viewOptions['gist']->setType($type); + $viewOptions['type_overrided'] = true; + } + } + $response = $this->createResponse('View/embedJs.html.twig', $viewOptions); $response->headers->set('Content-Type', 'text/javascript'); diff --git a/src/Gist/Resources/views/View/embed.html.twig b/src/Gist/Resources/views/View/embed.html.twig index 6f15c78..d1ee417 100644 --- a/src/Gist/Resources/views/View/embed.html.twig +++ b/src/Gist/Resources/views/View/embed.html.twig @@ -31,6 +31,12 @@ {% block nav %}{% endblock %} {% block body %} + {% set routeParams = app.request.attributes.get('_route_params') %} + + {% if type_overrided is defined %} + {% set routeParams = routeParams|merge({type: gist.type}) %} + {% endif %} +
    - {{ commit|slice(0, 10) }} + {{ commit|slice(0, 10) }} {% if not gist.cipher %} - + {{ 'gist.action.raw'|trans }} - + {{ 'gist.action.download'|trans }} {% endif %} - + {{ 'gist.action.clone'|trans }} diff --git a/src/Gist/Resources/views/View/embedJs.html.twig b/src/Gist/Resources/views/View/embedJs.html.twig index af08fd9..8e55f0b 100644 --- a/src/Gist/Resources/views/View/embedJs.html.twig +++ b/src/Gist/Resources/views/View/embedJs.html.twig @@ -1,10 +1,16 @@ +{% set routeParams = app.request.attributes.get('_route_params') %} + +{% if type_overrided is defined %} + {% set routeParams = routeParams|merge({type: gist.type}) %} +{% endif %} + (function() { var iFrameResizeLoaded = function() { var div = document.getElementById('gist-{{ gist.file }}-{{ commit }}'); var iframeId = 'gist-' + (Math.floor(Math.random() * (10000 - 1)) + 1).toString(); 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')) { url = [url, div.getAttribute('data-key')].join(''); } diff --git a/src/Gist/Resources/views/View/view.html.twig b/src/Gist/Resources/views/View/view.html.twig index 29ffc5d..0aed8e4 100644 --- a/src/Gist/Resources/views/View/view.html.twig +++ b/src/Gist/Resources/views/View/view.html.twig @@ -15,6 +15,12 @@ {% block title %}{{ gist.title ? gist.title : 'gist.untitled'|trans }} - {{ commit|slice(0, 10) }}{% endblock %} {% block body %} + {% set routeParams = app.request.attributes.get('_route_params') %} + + {% if type_overrided is defined %} + {% set routeParams = routeParams|merge({type: gist.type}) %} + {% endif %} + +
    +
    +
    +
    + + +
    +
    +
    +
    @@ -115,7 +148,7 @@
    {{ '
    -' }} +' }}
    From 196da8cb45a0544c663cf1eb124690a728f58664 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sat, 4 May 2019 19:05:52 +0200 Subject: [PATCH 78/79] upgrade npm packages --- Makefile | 2 ++ package.json | 8 ++++---- src/Gist/Resources/views/base.html.twig | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 2c7a213..6b5a389 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ npm: @echo ${NPM} install + ${NPM} update update: @echo "Updating application's dependencies" @@ -31,6 +32,7 @@ update: ${MKDIR} -p data/cache ${COMPOSER} update ${NPM} install + ${NPM} update clean-cache: @echo "Removing cache" diff --git a/package.json b/package.json index fcb0414..13c663e 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "dependencies": { - "bootstrap": "^3.3.4", - "diff": "^2.2.2", + "bootstrap": "^3.4.1", + "diff": "^2.2.3", "flag-icon-css": "^0.8.6", - "iframe-resizer": "^2.8.6", - "jquery": "^1.9.1" + "iframe-resizer": "^2.8.10", + "jquery": ">=3.4.0" } } diff --git a/src/Gist/Resources/views/base.html.twig b/src/Gist/Resources/views/base.html.twig index 3de1f18..6bebf64 100644 --- a/src/Gist/Resources/views/base.html.twig +++ b/src/Gist/Resources/views/base.html.twig @@ -117,7 +117,7 @@ return key; } - + From c9fee1ea427b56ce918127ac9cf3e748ed41e14a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 14 Jun 2019 12:07:08 +0200 Subject: [PATCH 79/79] [security] fix issue WS-2018-0590 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13c663e..c637d1f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "dependencies": { "bootstrap": "^3.4.1", - "diff": "^2.2.3", + "diff": "^3.5.0", "flag-icon-css": "^0.8.6", "iframe-resizer": "^2.8.10", "jquery": ">=3.4.0"