diff --git a/plugins/email/CHANGELOG.md b/plugins/email/CHANGELOG.md index f892ce1..78971ef 100644 --- a/plugins/email/CHANGELOG.md +++ b/plugins/email/CHANGELOG.md @@ -1,3 +1,25 @@ +# v4.0.4 +## 07/10/2023 + +1. [](#bugfix) + * Fix for email file attachments using stream + +# v4.0.3 +## 06/29/2023 + +1. [](#improved) + * Simplified the `Email::processRecipients()` logic for readability +1. [](#bugfix) + * Fix an issue with 2 email addresses provided with 'just' email and no name [#176](https://github.com/getgrav/grav-plugin-email/issues/176) + * Fix for blank subjectlines when using `Message::setSubject()` in Twig templates [getgrav/grav-plugin-login#299](https://github.com/getgrav/grav-plugin-login/issues/299) + +# v4.0.2 +## 06/27/2023 + +1. [](#bugfix) + * some recipient handling improvements. e.g. missing `bcc_name` throwing error + * Allow overriding of defaults with a form configuration. Use `null` to remove default email configuration + # v4.0.1 ## 05/20/2023 diff --git a/plugins/email/blueprints.yaml b/plugins/email/blueprints.yaml index 68c89de..d3a66a0 100644 --- a/plugins/email/blueprints.yaml +++ b/plugins/email/blueprints.yaml @@ -1,7 +1,7 @@ name: Email slug: email type: plugin -version: 4.0.1 +version: 4.0.4 testing: false description: Enables the emailing system for Grav icon: envelope diff --git a/plugins/email/classes/Email.php b/plugins/email/classes/Email.php index 617bbee..1bc7b1d 100644 --- a/plugins/email/classes/Email.php +++ b/plugins/email/classes/Email.php @@ -138,8 +138,9 @@ class Email $email = $message->getEmail(); // Extend parameters with defaults. - $params += [ + $defaults = [ 'bcc' => $config->get('plugins.email.bcc', []), + 'bcc_name' => $config->get('plugins.email.bcc_name'), 'body' => $config->get('plugins.email.body', '{% include "forms/data.html.twig" %}'), 'cc' => $config->get('plugins.email.cc', []), 'cc_name' => $config->get('plugins.email.cc_name'), @@ -157,6 +158,12 @@ class Email 'message' => $message ]; + foreach ($defaults as $key => $value) { + if (!key_exists($key, $params)) { + $params[$key] = $value; + } + } + if (!$params['to']) { throw new \RuntimeException($language->translate('PLUGIN_EMAIL.PLEASE_CONFIGURE_A_TO_ADDRESS')); } @@ -237,38 +244,39 @@ class Email */ protected function processRecipients(string $type, array $params): array { + if (array_key_exists($type, $params) && $params[$type] === null) { + return []; + } + $recipients = $params[$type] ?? Grav::instance()['config']->get('plugins.email.'.$type) ?? []; $list = []; if (!empty($recipients)) { - if (is_array($recipients) && Utils::isAssoc($recipients)) { - $list[] = $this->createAddress($recipients); + if (is_array($recipients)) { + if (Utils::isAssoc($recipients) || (count($recipients) ===2 && $this->isValidEmail($recipients[0]) && !$this->isValidEmail($recipients[1]))) { + $list[] = $this->createAddress($recipients); + } else { + foreach ($recipients as $recipient) { + $list[] = $this->createAddress($recipient); + } + } } else { - if (is_array($recipients)) { - if (count($recipients) ===2 && $this->isValidEmail($recipients[0]) && is_string($recipients[1])) { - $list[] = $this->createAddress($recipients); - } else { - foreach ($recipients as $recipient) { - $list[] = $this->createAddress($recipient); - } + if (is_string($recipients) && Utils::contains($recipients, ',')) { + $recipients = array_map('trim', explode(',', $recipients)); + foreach ($recipients as $recipient) { + $list[] = $this->createAddress($recipient); } } else { - if (is_string($recipients) && Utils::contains($recipients, ',')) { - $recipients = array_map('trim', explode(',', $recipients)); - foreach ($recipients as $recipient) { - $list[] = $this->createAddress($recipient); - } - } else { - if (!Utils::contains($recipients, ['<','>']) && ($params[$type."_name"])) { - $recipients = [$recipients, $params[$type."_name"]]; - } - $list[] = $this->createAddress($recipients); + if (!Utils::contains($recipients, ['<','>']) && (isset($params[$type."_name"]))) { + $recipients = [$recipients, $params[$type."_name"]]; } + $list[] = $this->createAddress($recipients); } } } + return $list; } diff --git a/plugins/email/classes/Message.php b/plugins/email/classes/Message.php index fb691f8..066a209 100644 --- a/plugins/email/classes/Message.php +++ b/plugins/email/classes/Message.php @@ -18,6 +18,12 @@ class Message return $this; } + public function setSubject($subject): self + { + $this->subject($subject); + return $this; + } + public function to($to): self { $this->email->to($to); diff --git a/plugins/email/email.php b/plugins/email/email.php index b96ff36..da59047 100644 --- a/plugins/email/email.php +++ b/plugins/email/email.php @@ -125,6 +125,7 @@ class EmailPlugin extends Plugin { // Build message $message = $this->email->buildMessage($params, $vars); + $locator = $this->grav['locator']; if (isset($params['attachments'])) { $filesToAttach = (array)$params['attachments']; @@ -135,9 +136,11 @@ class EmailPlugin extends Plugin if (isset($fileValues['file'])) { $filename = $fileValues['file']; } else { - $filename = ROOT_DIR . $fileValues['path']; + $filename = $fileValues['path']; } + $filename = $locator->findResource($filename, true, true); + try { $message->attachFromPath($filename); } catch (\Exception $e) { diff --git a/plugins/email/languages.yaml b/plugins/email/languages.yaml index 4cb044c..9f1fc7f 100644 --- a/plugins/email/languages.yaml +++ b/plugins/email/languages.yaml @@ -78,6 +78,7 @@ fr: PLUGIN_EMAIL: MAIL_ENGINE: "Moteur de messagerie" MAIL_ENGINE_DISABLED: "Désactivé" + MAIL_ENGINE_DESC: "NOTE : Si vous sélectionnez un moteur fourni par un autre plugin, vous devez configurer les options dans ce même plugin." CONTENT_TYPE: "Type de contenu" CONTENT_TYPE_PLAIN_TEXT: "Texte brut" CHARSET: "Jeu de caractères" @@ -130,7 +131,9 @@ fr: QUEUE_FLUSH_MSG_LIMIT: "Messages par Flush" QUEUE_FLUSH_MSG_LIMIT_APPEND: "Messages" QUEUE_FLUSH_TIME_LIMIT: "Délai de Flush" - QUEUE_FLUSH_TIME_LIMIT_APPEND: "Seconds" + QUEUE_FLUSH_TIME_LIMIT_APPEND: "Secondes" + EMAIL_FORMAT: "Utilisez le format `addr` : `email@adresse.org` ou le format `name-addr` : `Votre nom `. Séparer par des virgules pour plusieurs adresses." + hr: PLUGIN_EMAIL: diff --git a/plugins/form/CHANGELOG.md b/plugins/form/CHANGELOG.md index 87e9dbf..7c88629 100644 --- a/plugins/form/CHANGELOG.md +++ b/plugins/form/CHANGELOG.md @@ -1,3 +1,11 @@ +# v7.2.1 +## 06/27/2023 + +1. [](#improved) + * Added some optional debug output to help isolate form loading problems +1. [](#bugfix) + * More robust fix for multi-language form caching + # v7.2.0 ## 06/21/2023 diff --git a/plugins/form/blueprints.yaml b/plugins/form/blueprints.yaml index 094eaa4..4a7ec33 100644 --- a/plugins/form/blueprints.yaml +++ b/plugins/form/blueprints.yaml @@ -1,7 +1,7 @@ name: Form slug: form type: plugin -version: 7.2.0 +version: 7.2.1 description: Enables forms handling and processing icon: check-square author: @@ -34,6 +34,17 @@ form: title: PLUGIN_FORM.GENERAL fields: + debug: + type: toggle + label: Debug + highlight: 1 + default: 0 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + built_in_css: type: toggle label: PLUGIN_FORM.USE_BUILT_IN_CSS diff --git a/plugins/form/form.php b/plugins/form/form.php index 9ed14b1..02eae7a 100644 --- a/plugins/form/form.php +++ b/plugins/form/form.php @@ -26,6 +26,7 @@ use Grav\Plugin\Form\Form; use Grav\Plugin\Form\Forms; use Grav\Plugin\Form\TwigExtension; use Grav\Common\HTTP\Client; +use Monolog\Logger; use ReCaptcha\ReCaptcha; use ReCaptcha\RequestMethod\CurlPost; use RecursiveArrayIterator; @@ -66,6 +67,7 @@ class FormPlugin extends Plugin /** @var array */ protected $json_response = []; + /** * @return bool */ @@ -147,6 +149,8 @@ class FormPlugin extends Plugin 'onTwigSiteVariables' => ['onTwigVariables', 0], 'onFormValidationProcessed' => ['onFormValidationProcessed', 0], ]); + + } /** @@ -224,9 +228,8 @@ class FormPlugin extends Plugin /** @var PageInterface $page */ $page = $this->grav['page']; - // Force rebuild form when form has not been built and form cache expired. - // This happens when form cache expires before the page cache - // and then does not trigger 'onPageProcessed' event. + + // DEPRECATED: This should no longer ever happen if (!$this->forms) { $this->onPageProcessed(new Event(['page' => $page])); } @@ -311,9 +314,11 @@ class FormPlugin extends Plugin /** @var Forms $forms */ $forms = $this->grav['forms']; + $lang = $this->grav['language']->getLanguage(); + /** @var Route $route */ $route = $this->grav['route']; - $pageForms = $this->forms[$route->getRoute()] ?? []; + $pageForms = $this->forms[$lang][$route->getRoute()] ?? []; /** * @var string $name @@ -828,10 +833,11 @@ class FormPlugin extends Plugin public function addFormDefinition(PageInterface $page, string $name, array $form): void { $route = ($page->home() ? '/' : $page->route()) ?? '/'; + $lang = $this->grav['language']->getLanguage(); - if (!isset($this->forms[$route][$name])) { + if (!isset($this->forms[$lang][$route][$name])) { $form['_page_routable'] = !$page->isModule(); - $this->forms[$route][$name] = $form; + $this->forms[$lang][$route][$name] = $form; $this->saveCachedForms(); } } @@ -849,12 +855,13 @@ class FormPlugin extends Plugin return; } + $lang = $this->grav['language']->getLanguage(); $name = $form->getName(); - if (!isset($this->forms[$route][$name])) { + if (!isset($this->forms[$lang][$route][$name])) { $form['_page_routable'] = true; - $this->forms[$route][$name] = $form; + $this->forms[$lang][$route][$name] = $form; $this->saveCachedForms(); } } @@ -869,6 +876,7 @@ class FormPlugin extends Plugin { /** @var Pages $pages */ $pages = $this->grav['pages']; + $lang = $this->grav['language']->getLanguage(); // Handle parameters. if (is_array($data)) { @@ -914,7 +922,7 @@ class FormPlugin extends Plugin // Attempt to find the form from the page. if ('' !== $route) { - $forms = $this->forms[$route] ?? []; + $forms = $this->forms[$lang][$route] ?? []; if (!$unnamed) { // Get form by the name. @@ -930,9 +938,7 @@ class FormPlugin extends Plugin if (null === $form) { // First check if we requested a specific form which didn't exist. if ($route_provided || $unnamed) { - /** @var Debugger $debugger */ - $debugger = $this->grav['debugger']; - $debugger->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning'); + $this->grav['debugger']->addMessage(sprintf('Form %s not found in page %s', $name ?? 'unnamed', $route), 'warning'); return null; } @@ -946,8 +952,7 @@ class FormPlugin extends Plugin // Check for naming conflicts. if (count($forms) > 1) { - $debugger = $this->grav['debugger']; - $debugger->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning'); + $this->grav['debugger']->addMessage(sprintf('Fetching form by its name, but there are multiple pages with the same form name %s', $name), 'warning'); } [$route, $name, $form] = $first; @@ -959,9 +964,7 @@ class FormPlugin extends Plugin if (is_array($form)) { // Form was cached as an array, try to create the object. if (null === $page) { - /** @var Debugger $debugger */ - $debugger = $this->grav['debugger']; - $debugger->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning'); + $this->grav['debugger']->addMessage(sprintf('Form %s cannot be created as page %s does not exist', $name, $route), 'warning'); return null; } @@ -1096,7 +1099,10 @@ class FormPlugin extends Plugin protected function findFormByName(string $name): array { $list = []; - foreach ($this->forms as $route => $forms) { + $lang = $this->grav['language']->getLanguage(); + $lang_forms = $this->forms[$lang] ?? []; + + foreach ($lang_forms as $route => $forms) { foreach ($forms as $key => $form) { if ($name === $key && !empty($form['_page_routable'])) { $list[] = [$route, $key, $form]; @@ -1233,12 +1239,9 @@ class FormPlugin extends Plugin /** @var Cache $cache */ $cache = $this->grav['cache']; - [$forms] = $cache->fetch($this->getFormCacheId()); + $forms = $cache->fetch($this->getFormCacheId()); } catch (Exception $e) { - /** @var Debugger $debugger */ - $debugger = Grav::instance()['debugger']; - $debugger->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error'); - + $this->grav['debugger']->addMessage(sprintf('Unserializing cached forms failed: %s', $e->getMessage()), 'error'); $forms = null; } @@ -1248,7 +1251,11 @@ class FormPlugin extends Plugin // Only update the forms if it's not empty if ($forms) { - $this->forms = array_merge($this->forms, $forms); + $this->forms = Utils::arrayMergeRecursiveUnique($this->forms, $forms); + if ($this->config()['debug']) { + $this->grav['log']->addDebug(sprintf("<<<< Loaded cached forms: %s\n%s", $this->getFormCacheId(), $this->arrayToString($this->forms))); + } + } } @@ -1261,8 +1268,17 @@ class FormPlugin extends Plugin { /** @var Cache $cache */ $cache = $this->grav['cache']; + $cache_id = $this->getFormCacheId(); - $cache->save($this->getFormCacheId(), [$this->forms]); + $forms = $cache->fetch($cache_id); + if ($forms) { + $this->forms = Utils::arrayMergeRecursiveUnique($this->forms, $forms); + } + + $cache->save($cache_id, $this->forms); + if ($this->config()['debug']) { + $this->grav['log']->addDebug(sprintf(">>>> Saved cached forms: %s\n%s", $this->getFormCacheId(), $this->arrayToString($this->forms))); + } } /** @@ -1272,10 +1288,10 @@ class FormPlugin extends Plugin */ protected function getFormCacheId(): string { - /** @var Pages $pages */ - $pages = $this->grav['pages']; - - return $pages->getPagesCacheId() . '-form-plugin'; + /** @var \Grav\Common\Cache $cache */ + $cache = $this->grav['cache']; + $cache_id = $cache->getKey() . '-form-plugin'; + return $cache_id; } /** @@ -1308,4 +1324,25 @@ class FormPlugin extends Plugin exit; } } + + protected function arrayToString($array, $level = 2) { + $result = $this->limitArrayLevels($array, $level); + return json_encode($result, JSON_UNESCAPED_SLASHES); + } + + protected function limitArrayLevels($array, $levelsToKeep, $currentLevel = 0) { + if ($currentLevel >= $levelsToKeep) { + return '-'; + } + + $result = []; + foreach ($array as $key => $value) { + if (is_array($value)) { + $value = $this->limitArrayLevels($value, $levelsToKeep, $currentLevel + 1); + } + $result[$key] = $value; + } + + return $result; + } } diff --git a/plugins/form/form.yaml b/plugins/form/form.yaml index 29793ca..27124a0 100644 --- a/plugins/form/form.yaml +++ b/plugins/form/form.yaml @@ -3,6 +3,7 @@ built_in_css: true inline_css: true refresh_prevention: false client_side_validation: true +debug: false inline_errors: false files: multiple: false # To allow multiple files, default is single diff --git a/plugins/login/CHANGELOG.md b/plugins/login/CHANGELOG.md index bd230d5..a360aac 100644 --- a/plugins/login/CHANGELOG.md +++ b/plugins/login/CHANGELOG.md @@ -1,9 +1,15 @@ +# v3.7.6 +## 06/29/2023 + +1. [](#bugfix) + * Don't save an empty user file on password reset of non-existing user + # v3.7.5 ## 06/14/2023 1. [](#bugfix) * Sanitized `email` during the "forgot password" process to protect against XSS attacks - * Fixed an account enumeration vulneratiblity in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293) + * Fixed an account enumeration vulnerability in forgot password [#293](https://github.com/getgrav/grav-plugin-login/pull/293) # v3.7.4 ## 05/09/2023 diff --git a/plugins/login/blueprints.yaml b/plugins/login/blueprints.yaml index bd7b61b..ce93d34 100644 --- a/plugins/login/blueprints.yaml +++ b/plugins/login/blueprints.yaml @@ -1,7 +1,7 @@ name: Login slug: login type: plugin -version: 3.7.5 +version: 3.7.6 testing: false description: Enables user authentication and login screen. icon: sign-in diff --git a/plugins/login/classes/Controller.php b/plugins/login/classes/Controller.php index 9421cdd..ed006d7 100644 --- a/plugins/login/classes/Controller.php +++ b/plugins/login/classes/Controller.php @@ -347,61 +347,66 @@ class Controller $config = $this->grav['config']; $data = $this->post; + /** @var Language $language */ + $language = $this->grav['language']; + $messages = $this->grav['messages']; + /** @var UserCollectionInterface $users */ $users = $this->grav['accounts']; - $email = $data['email'] ?? ''; // Sanitize $email $email = htmlspecialchars(strip_tags($email), ENT_QUOTES, 'UTF-8'); - $user = !empty($email) ? $users->find($email, ['email']) : null; + // Find user if they exist + $user = $users->find($email, ['email']); - /** @var Language $language */ - $language = $this->grav['language']; - $messages = $this->grav['messages']; + if ($user->exists()) { + if (!isset($this->grav['Email'])) { + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); + $this->setRedirect($this->login->getRoute('forgot') ?? '/'); - if (!isset($this->grav['Email'])) { - $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); - $this->setRedirect($this->login->getRoute('forgot') ?? '/'); + return true; + } - return true; - } + $from = $config->get('plugins.email.from'); - $from = $config->get('plugins.email.from'); + if (empty($from)) { + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); + $this->setRedirect($this->login->getRoute('forgot') ?? '/'); - if (empty($from)) { - $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_EMAIL_NOT_CONFIGURED'), 'error'); - $this->setRedirect($this->login->getRoute('forgot') ?? '/'); + return true; + } - return true; - } + $userKey = $user->username; + $rateLimiter = $this->login->getRateLimiter('pw_resets'); + $rateLimiter->registerRateLimitedAction($userKey); - $userKey = $user->username; - $rateLimiter = $this->login->getRateLimiter('pw_resets'); - $rateLimiter->registerRateLimitedAction($userKey); + if ($rateLimiter->isRateLimited($userKey)) { + $messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error'); + $this->setRedirect($this->login->getRoute('login') ?? '/'); - if ($rateLimiter->isRateLimited($userKey)) { - $messages->add($language->translate(['PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $email, $rateLimiter->getInterval()]), 'error'); - $this->setRedirect($this->login->getRoute('login') ?? '/'); + return true; + } - return true; - } + $token = md5(uniqid((string)mt_rand(), true)); + $expire = time() + 604800; // next week - $token = md5(uniqid((string)mt_rand(), true)); - $expire = time() + 604800; // next week + $user->reset = $token . '::' . $expire; + $user->save(); - $user->reset = $token . '::' . $expire; - $user->save(); - - try { - Email::sendResetPasswordEmail($user); + try { + Email::sendResetPasswordEmail($user); + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info'); + } catch (\Exception $e) { + $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error'); + } + } else { $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_INSTRUCTIONS_SENT_VIA_EMAIL'), 'info'); - } catch (\Exception $e) { - $messages->add($language->translate('PLUGIN_LOGIN.FORGOT_FAILED_TO_EMAIL'), 'error'); } + $this->setRedirect($this->login->getRoute('login') ?? '/'); return true; diff --git a/plugins/markdown-notices/CHANGELOG.md b/plugins/markdown-notices/CHANGELOG.md new file mode 100644 index 0000000..87e27b1 --- /dev/null +++ b/plugins/markdown-notices/CHANGELOG.md @@ -0,0 +1,38 @@ +# v1.1.0 +## 12/02/2020 + +1. [](#new) + * Support for indent-sensitive notices [#17](https://github.com/getgrav/grav-plugin-markdown-notices/pull/17) + * Pass phpstan level 1 tests + * Require Grav v1.6 + +# v1.0.4 +## 09/10/2019 + +1. [](#improved) + * Reverted PR#10 which was breaking multiline notices and also unintentionally marking up notices with `!` in paragraphs + +# v1.0.3 +## 08/16/2019 + +1. [](#improved) + * Fixed issue where PR#10 clobbered PR#9 + +# v1.0.2 +## 08/11/2019 + +1. [](#new) + * Ability to specify your own base classes [#9](https://github.com/getgrav/grav-plugin-markdown-notices/pull/9) + * Allow adding inline notices inside tables [#10](https://github.com/getgrav/grav-plugin-markdown-notices/pull/10) + +# v1.0.1 +## 03/09/2018 + +1. [](#improved) + * Updated blueprint file + +# v1.0.0 +## 12/22/2015 + +1. [](#new) + * ChangeLog started... diff --git a/plugins/markdown-notices/LICENSE b/plugins/markdown-notices/LICENSE new file mode 100644 index 0000000..4bb7092 --- /dev/null +++ b/plugins/markdown-notices/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Grav + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/markdown-notices/README.md b/plugins/markdown-notices/README.md new file mode 100644 index 0000000..00f9cb6 --- /dev/null +++ b/plugins/markdown-notices/README.md @@ -0,0 +1,62 @@ +# Grav Markdown Notices Plugin + +The **markdown-notices plugin** for [Grav](http://github.com/getgrav/grav) allows generation of notice blocks of text via markdown: + +![](assets/screenshot.png) + +# Installation + +This plugin is easy to install with GPM. + +``` +$ bin/gpm install markdown-notices +``` + +# Configuration + +Simply copy the `user/plugins/markdown-notices/markdown-notices.yaml` into `user/config/plugins/markdown-notices.yaml` and make your modifications. + +``` +enabled: true +built_in_css: true +base_classes: 'notices' +level_classes: [yellow, red, blue, green] +``` + +# Examples + +Using one level of `!` + +``` +! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris feugiat quam erat, ut iaculis diam posuere nec. +! Vestibulum eu condimentum urna. Vestibulum feugiat odio ut sodales porta. Donec sit amet ante mi. Donec lobortis +! orci dolor. Donec tristique volutpat ultricies. Nullam tempus, enim sit amet fringilla facilisis, ipsum ex +! tincidunt ipsum, vel placerat sem sem vitae risus. Aenean posuere sed purus nec pretium. +``` + +You will output the following HTML + +``` +
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris feugiat quam erat, ut iaculis diam posuere nec. + Vestibulum eu condimentum urna. Vestibulum feugiat odio ut sodales porta. Donec sit amet ante mi. Donec lobortis + orci dolor. Donec tristique volutpat ultricies. Nullam tempus, enim sit amet fringilla facilisis, ipsum ex + tincidunt ipsum, vel placerat sem sem vitae risus. Aenean posuere sed purus nec pretium. +

+
+``` + +The `notices` class determined by the `base_classes` and `yellow` class is determined by the `level_classes` in the configuration. You can customize this as you need. + +``` +!! Lorem ipsum dolor sit amet, **consectetur adipiscing** elit. Mauris feugiat quam erat, ut iaculis diam posuere nec. +!! +!! * List item a +!! * List item b +!! +!! orci dolor. Donec tristique volutpat ultricies. Nullam tempus, enim sit amet fringilla facilisis, ipsum ex +!! tincidunt ipsum, vel placerat sem sem vitae risus. Aenean posuere sed purus nec pretium. +``` + +Two levels of `!!` will use the second level class etc. You can also use complex markdown inside the notices. diff --git a/plugins/markdown-notices/assets/notices.css b/plugins/markdown-notices/assets/notices.css new file mode 100644 index 0000000..93c3a85 --- /dev/null +++ b/plugins/markdown-notices/assets/notices.css @@ -0,0 +1,32 @@ +.notices { + padding: 1px 1px 1px 30px; + margin: 15px 0; +} + +.notices p { + +} + +.notices.yellow { + border-left: 10px solid #f0ad4e; + background: #fcf8f2; + color: #df8a13; +} + +.notices.red { + border-left: 10px solid #d9534f; + background: #fdf7f7; + color: #b52b27; +} + +.notices.blue { + border-left: 10px solid #5bc0de; + background: #f4f8fa; + color: #28a1c5; +} + +.notices.green { + border-left: 10px solid #5cb85c; + background: #f1f9f1; + color: #3d8b3d; +} \ No newline at end of file diff --git a/plugins/markdown-notices/assets/screenshot.png b/plugins/markdown-notices/assets/screenshot.png new file mode 100644 index 0000000..cf27677 Binary files /dev/null and b/plugins/markdown-notices/assets/screenshot.png differ diff --git a/plugins/markdown-notices/blueprints.yaml b/plugins/markdown-notices/blueprints.yaml new file mode 100644 index 0000000..601b98a --- /dev/null +++ b/plugins/markdown-notices/blueprints.yaml @@ -0,0 +1,59 @@ +name: 'Markdown Notices' +type: plugin +slug: markdown-notices +version: 1.1.0 +description: 'Adds the ability to render notices blocks in Markdown' +icon: asterisk +author: + name: Team Grav + email: devs@getgrav.org + url: http://getgrav.org +homepage: https://github.com/getgrav/grav-plugin-markdown-notices +license: MIT +dependencies: + - { name: grav, version: '>=1.6.0' } + +form: + validation: strict + fields: + enabled: + type: toggle + label: PLUGIN_ADMIN.PLUGIN_STATUS + highlight: 1 + default: 0 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + + built_in_css: + type: toggle + label: PLUGIN_MARKDOWN_NOTICES.USE_BUILT_IN_CSS + highlight: 1 + default: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + + base_classes: + type: selectize + label: PLUGIN_MARKDOWN_NOTICES.BASE_CLASSES + size: large + placeholder: PLUGIN_MARKDOWN_NOTICES.BASE_CLASSES_PLACEHOLDER + help: PLUGIN_MARKDOWN_NOTICES.BASE_CLASSES_HELP + classes: fancy + validate: + type: string + + level_classes: + type: selectize + label: PLUGIN_MARKDOWN_NOTICES.LEVEL_CLASSES + size: large + placeholder: PLUGIN_MARKDOWN_NOTICES.LEVEL_CLASSES_PLACEHOLDER + help: PLUGIN_MARKDOWN_NOTICES.LEVEL_CLASSES_HELP + classes: fancy + validate: + type: commalist diff --git a/plugins/markdown-notices/composer.json b/plugins/markdown-notices/composer.json new file mode 100644 index 0000000..b5f3540 --- /dev/null +++ b/plugins/markdown-notices/composer.json @@ -0,0 +1,27 @@ +{ + "name": "grav-plugin-markdown-notices", + "type": "grav-plugin", + "description": "Markdown notices plugin for Grav CMS", + "keywords": ["notices"], + "homepage": "https://github.com/getgrav/grav-plugin-markdown-notices/", + "license": "MIT", + "authors": [ + { + "name": "Team Grav", + "email": "devs@getgrav.org", + "homepage": "http://getgrav.org", + "role": "Developer" + } + ], + "require": { + "php": ">=7.1.3" + }, + "autoload": { + "classmap": ["markdown-notices.php"] + }, + "config": { + "platform": { + "php": "7.1.3" + } + } +} diff --git a/plugins/markdown-notices/composer.lock b/plugins/markdown-notices/composer.lock new file mode 100644 index 0000000..428bd2b --- /dev/null +++ b/plugins/markdown-notices/composer.lock @@ -0,0 +1,22 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "683006688355ff7a1f71b2726c2629b6", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.1.3" + }, + "platform-dev": [], + "platform-overrides": { + "php": "7.1.3" + } +} diff --git a/plugins/markdown-notices/languages.yaml b/plugins/markdown-notices/languages.yaml new file mode 100644 index 0000000..dbee759 --- /dev/null +++ b/plugins/markdown-notices/languages.yaml @@ -0,0 +1,29 @@ +en: + PLUGIN_MARKDOWN_NOTICES: + USE_BUILT_IN_CSS: 'Use built-in CSS' + BASE_CLASSES: 'Base classes' + BASE_CLASSES_HELP: 'These classes will be added before the class level' + BASE_CLASSES_PLACEHOLDER: 'e.g. notices' + LEVEL_CLASSES: 'Level classes' + LEVEL_CLASSES_HELP: 'The classes to use for each level of notices depth' + LEVEL_CLASSES_PLACEHOLDER: 'e.g. yellow, red, blue, green' + +ru: + PLUGIN_MARKDOWN_NOTICES: + USE_BUILT_IN_CSS: 'Использовать встроенный CSS' + BASE_CLASSES: 'Базовые классы' + BASE_CLASSES_HELP: 'Эти классы будут добавлены до уровня класса' + BASE_CLASSES_PLACEHOLDER: 'например notices' + LEVEL_CLASSES: 'Классы уровней' + LEVEL_CLASSES_HELP: 'Эти классы используются на каждом уровне глубины уведомлений' + LEVEL_CLASSES_PLACEHOLDER: 'например yellow, red, blue, green' + +uk: + PLUGIN_MARKDOWN_NOTICES: + USE_BUILT_IN_CSS: 'Використовувати вбудований CSS' + BASE_CLASSES: 'Базові класи' + BASE_CLASSES_HELP: 'Ці класи будуть додані до рівня класу' + BASE_CLASSES_PLACEHOLDER: 'наприклад notices' + LEVEL_CLASSES: 'Класи рівнів' + LEVEL_CLASSES_HELP: 'Ці класи використовуються на кожному рівні глибини повідомлень' + LEVEL_CLASSES_PLACEHOLDER: 'наприклад yellow, red, blue, green' diff --git a/plugins/markdown-notices/markdown-notices.php b/plugins/markdown-notices/markdown-notices.php new file mode 100644 index 0000000..3829e2a --- /dev/null +++ b/plugins/markdown-notices/markdown-notices.php @@ -0,0 +1,92 @@ + [ + ['autoload', 100001], + ], + 'onMarkdownInitialized' => ['onMarkdownInitialized', 0], + 'onTwigSiteVariables' => ['onTwigSiteVariables', 0] + ]; + } + + /** + * [onPluginsInitialized:100000] Composer autoload. + * + * @return ClassLoader + */ + public function autoload() + { + return require __DIR__ . '/vendor/autoload.php'; + } + + public function onMarkdownInitialized(Event $event) + { + $markdown = $event['markdown']; + + $markdown->addBlockType('!', 'Notices', true, false); + + $markdown->blockNotices = function($Line) { + + $this->level_classes = $this->config->get('plugins.markdown-notices.level_classes'); + $this->base_classes = $this->config->get('plugins.markdown-notices.base_classes'); + + if (preg_match('/^(!{1,'.count($this->level_classes).'}) (.*)/', $Line['text'], $matches)) + { + $level = strlen($matches[1]) - 1; + + $text = $matches[2]; + $base_classes = (empty($this->base_classes)) ? '' : str_replace(',', ' ', $this->base_classes) . ' '; + + $Block = [ + 'element' => [ + 'name' => 'div', + 'handler' => 'lines', + 'attributes' => [ + 'class' => $base_classes . $this->level_classes[$level], + ], + 'text' => (array) $text, + ], + ]; + + return $Block; + } + }; + + $markdown->blockNoticesContinue = function($Line, array $Block) { + if (isset($Block['interrupted'])) + { + return; + } + + if (preg_match('/^(!{1,'.count($this->level_classes).'}) ?(.*)/', $Line['text'], $matches)) + { + $Block['element']['text'] []= $matches[2]; + + return $Block; + } + }; + } + + public function onTwigSiteVariables() + { + if ($this->config->get('plugins.markdown-notices.built_in_css')) { + $this->grav['assets'] + ->add('plugin://markdown-notices/assets/notices.css'); + } + } +} diff --git a/plugins/markdown-notices/markdown-notices.yaml b/plugins/markdown-notices/markdown-notices.yaml new file mode 100644 index 0000000..2e15749 --- /dev/null +++ b/plugins/markdown-notices/markdown-notices.yaml @@ -0,0 +1,4 @@ +enabled: true +built_in_css: true +base_classes: 'notices' +level_classes: [yellow, red, blue, green] diff --git a/plugins/markdown-notices/vendor/autoload.php b/plugins/markdown-notices/vendor/autoload.php new file mode 100644 index 0000000..e0aa508 --- /dev/null +++ b/plugins/markdown-notices/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath.'\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/plugins/markdown-notices/vendor/composer/LICENSE b/plugins/markdown-notices/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/plugins/markdown-notices/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/plugins/markdown-notices/vendor/composer/autoload_classmap.php b/plugins/markdown-notices/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..2c14f6c --- /dev/null +++ b/plugins/markdown-notices/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $baseDir . '/markdown-notices.php', +); diff --git a/plugins/markdown-notices/vendor/composer/autoload_namespaces.php b/plugins/markdown-notices/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/plugins/markdown-notices/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit83fb2a7c0fd89ecaed52b0401a5f24c0::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/plugins/markdown-notices/vendor/composer/autoload_static.php b/plugins/markdown-notices/vendor/composer/autoload_static.php new file mode 100644 index 0000000..f5cb969 --- /dev/null +++ b/plugins/markdown-notices/vendor/composer/autoload_static.php @@ -0,0 +1,20 @@ + __DIR__ . '/../..' . '/markdown-notices.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->classMap = ComposerStaticInit83fb2a7c0fd89ecaed52b0401a5f24c0::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/plugins/markdown-notices/vendor/composer/installed.json b/plugins/markdown-notices/vendor/composer/installed.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/plugins/markdown-notices/vendor/composer/installed.json @@ -0,0 +1 @@ +[]