From 5ccfa24b27193b744d8da0d01f081a1b6a8bb56b Mon Sep 17 00:00:00 2001
From: Denis Flaven
Date: Wed, 21 Nov 2018 19:36:51 +0100
Subject: [PATCH] iTop Newsroom implementation - painfully merged manually...
---
application/applicationextension.inc.php | 2 +
application/itopwebpage.class.inc.php | 72 ++++
application/newsroomprovider.class.inc.php | 143 +++++++
core/config.class.inc.php | 8 +
core/metamodel.class.php | 2 +-
css/light-grey.css | 162 ++++++--
css/light-grey.scss | 141 ++++++-
datamodels/2.x/itop-hub-connector/css/hub.css | 59 +--
.../datamodel.itop-hub-connector.xml | 4 +-
.../hubnewsroomprovider.class.inc.php | 74 ++++
.../module.itop-hub-connector.php | 3 +-
dictionaries/de.dictionary.itop.ui.php | 14 +
dictionaries/en.dictionary.itop.ui.php | 14 +
dictionaries/fr.dictionary.itop.ui.php | 14 +
dictionaries/nl.dictionary.itop.ui.php | 14 +
dictionaries/ru.dictionary.itop.ui.php | 14 +
images/newsroom_menu.png | Bin 0 -> 302 bytes
js/newsroom_menu.js | 350 ++++++++++++++++++
js/showdown.min.js | 3 +
pages/preferences.php | 120 ++++++
20 files changed, 1118 insertions(+), 95 deletions(-)
create mode 100644 application/newsroomprovider.class.inc.php
create mode 100644 datamodels/2.x/itop-hub-connector/hubnewsroomprovider.class.inc.php
create mode 100644 images/newsroom_menu.png
create mode 100644 js/newsroom_menu.js
create mode 100644 js/showdown.min.js
diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php
index d92e41e49..d8e85b39e 100644
--- a/application/applicationextension.inc.php
+++ b/application/applicationextension.inc.php
@@ -16,6 +16,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see
+require_once(APPROOT.'application/newsroomprovider.class.inc.php');
+
/**
* Management of application plugins
*
diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php
index baee0de1c..dd9dac042 100644
--- a/application/itopwebpage.class.inc.php
+++ b/application/itopwebpage.class.inc.php
@@ -105,6 +105,8 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_linked_script('../js/jquery.magnific-popup.min.js');
$this->add_linked_script('../js/breadcrumb.js');
$this->add_linked_script('../js/moment-with-locales.min.js');
+ $this->add_linked_script('../js/showdown.min.js');
+ $this->add_linked_script('../js/newsroom_menu.js');
$this->add_dict_entry('UI:FillAllMandatoryFields');
@@ -257,6 +259,10 @@ EOF;
}
$this->add_script(
<<< EOF
+ function GetUserLanguage()
+ {
+ return $sJSLangShort;
+ }
function PrepareWidgets()
{
// note: each action implemented here must be idempotent,
@@ -794,6 +800,69 @@ EOF
ApplicationMenu::DisplayMenu($this, $oAppContext->GetAsHash());
}
+ /**
+ * Handles the "newsroom" menu at the top-right of the screen
+ */
+ protected function InitNewsroom()
+ {
+ $sNewsroomInitialImage = '';
+ if (MetaModel::GetConfig()->Get('newsroom_enabled') !== false)
+ {
+ $oUser = UserRights::GetUserObject();
+ /**
+ * @var iNewsroomProvider[] $aProviders
+ */
+ $aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
+ $aProviderParams = array();
+ foreach($aProviders as $oProvider)
+ {
+ $oProvider->SetConfig(MetaModel::GetConfig());
+ $bProviderEnabled = appUserPreferences::GetPref('newsroom_provider_'.get_class($oProvider), true);
+ if ($bProviderEnabled && $oProvider->IsApplicable($oUser))
+ {
+ $aProviderParams[] = array(
+ 'label' => $oProvider->GetLabel(),
+ 'fetch_url' => $oProvider->GetFetchURL(),
+ 'view_all_url' => $oProvider->GetViewAllURL(),
+ 'mark_all_as_read_url' => $oProvider->GetMarkAllAsReadURL(),
+ 'ttl' => $oProvider->GetTTL(),
+ );
+ }
+ }
+ if (count($aProviderParams) > 0)
+ {
+ $sImageUrl= '../images/newsroom_menu.png';
+ $sPlaceholderImageUrl= '../images/news-32x32.png';
+ $aParams = array(
+ 'image_url' => $sImageUrl,
+ 'placeholder_image_url' => $sPlaceholderImageUrl,
+ 'cache_uuid' => 'itop-newsroom-'.md5(APPROOT),
+ 'providers' => $aProviderParams,
+ 'display_limit' => (int)appUserPreferences::GetPref('newsroom_display_size', 7),
+ 'labels' => array(
+ 'no_message' => Dict::S('UI:Newsroom:NoNewMessage'),
+ 'mark_all_as_read' => Dict::S('UI:Newsroom:MarkAllAsRead'),
+ 'view_all' => Dict::S('UI:Newsroom:ViewAllMessages'),
+ ),
+ );
+ $sParams = json_encode($aParams);
+ $this->add_ready_script(
+<<';
+ }
+ else
+ {
+ // No newsroom menu at all
+ }
+ }
+ // else no newsroom menu
+ return $sNewsroomInitialImage;
+ }
+
+
/**
* Outputs (via some echo) the complete HTML page by assembling all its elements
*/
@@ -891,6 +960,8 @@ EOF
);
}
+ $sNewsRoomInitialImage = $this->InitNewsroom();
+
$this->outputCollapsibleSectionInit();
if ($this->GetOutputFormat() == 'html')
@@ -1273,6 +1344,7 @@ EOF;
$sHtml .= ' ';
$sHtml .= ' ';
diff --git a/application/newsroomprovider.class.inc.php b/application/newsroomprovider.class.inc.php
new file mode 100644
index 000000000..dca4bc022
--- /dev/null
+++ b/application/newsroomprovider.class.inc.php
@@ -0,0 +1,143 @@
+
+
+/**
+ * A provider for messages to be displayed in the iTop Newsroom
+ */
+interface iNewsroomProvider
+{
+ /**
+ * Inject the current configuration in the provider
+ * @param Config $oConfig
+ * @return void
+ */
+ public function SetConfig(Config $oConfig);
+
+ /**
+ * Tells if this provider is enabled for the given user
+ * @param User $oUser The user for who to check if the provider is applicable.
+ * return bool
+ */
+ public function IsApplicable(User $oUser = null);
+
+ /**
+ * The human readable (localized) label for this provider
+ * @return string
+ */
+ public function GetLabel();
+
+ /**
+ * The URL to query (from the browser, using jsonp) to fetch all unread messages
+ * @return string
+ */
+ public function GetFetchURL();
+
+ /**
+ * The URL to navigate to in order to display all messages
+ * @return string
+ */
+ public function GetViewAllURL();
+
+ /**
+ * The URL to query(from the browser, using jsonp) to mark all unread messages as read
+ * @return string
+ */
+ public function GetMarkAllAsReadURL();
+
+ /**
+ * Return the URL to configure the preferences for this provider or null is there is nothing to configure
+ * @return string|null
+ */
+ public function GetPreferencesUrl();
+
+ /**
+ * The duration between to refreshes of the cache (in seconds)
+ * @return int
+ */
+ public function GetTTL();
+}
+
+/**
+ * Basic implementation of a Newsroom provider, to be overloaded by your own provider implementation
+ *
+ */
+abstract class NewsroomProviderBase implements iNewsroomProvider
+{
+ /**
+ * The current configuration parameters
+ * @var Config
+ */
+ protected $oConfig;
+
+ public function __construct()
+ {
+ $this->oConfig = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see iNewsroomProvider::SetConfig()
+ */
+ public function SetConfig(Config $oConfig)
+ {
+ $this->oConfig = $oConfig;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see iNewsroomProvider::GetPreferencesUrl()
+ */
+ public function GetPreferencesUrl()
+ {
+ return null; // No preferences
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see iNewsroomProvider::GetLabel()
+ */
+ public abstract function GetLabel();
+
+ /**
+ * {@inheritDoc}
+ * @see iNewsroomProvider::GetFetchURL()
+ */
+ public abstract function GetFetchURL();
+
+ /**
+ * {@inheritDoc}
+ * @see iNewsroomProvider::GetMarkAllURL()
+ */
+ public abstract function GetMarkAllAsReadURL();
+
+ /**
+ * {@inheritDoc}
+ * @see iNewsroomProvider::GetViewAllURL()
+ */
+ public abstract function GetViewAllURL();
+
+ public function IsApplicable(User $oUser = null)
+ {
+ return false;
+ }
+
+ public function GetTTL()
+ {
+ return 10*60; // Refresh every 10 minutes
+ }
+}
diff --git a/core/config.class.inc.php b/core/config.class.inc.php
index 2d0638e9a..63b430b8b 100644
--- a/core/config.class.inc.php
+++ b/core/config.class.inc.php
@@ -1142,6 +1142,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
+ 'newsroom_enabled' => array(
+ 'type' => 'bool',
+ 'description' => 'Whether or not the whole newsroom is enabled',
+ 'default' => true,
+ 'value' => true,
+ 'source_of_value' => '',
+ 'show_in_conf_sample' => false,
+ ),
);
public function IsProperty($sPropCode)
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index d65dbde60..71c9d4990 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -2668,7 +2668,7 @@ abstract class MetaModel
// Build the list of available extensions
//
- $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface');
+ $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider');
foreach($aInterfaces as $sInterface)
{
self::$m_aExtensionClasses[$sInterface] = array();
diff --git a/css/light-grey.css b/css/light-grey.css
index 4b46f987b..dae9c3fa3 100644
--- a/css/light-grey.css
+++ b/css/light-grey.css
@@ -552,6 +552,9 @@ div.actions_menu > ul > li {
padding: 0;
height: 25px;
}
+.itop_popup > ul > li > ul, #logOffBtn > ul > li > ul {
+ box-shadow: 3px 3px 5px 0px rgba(0, 0, 0, 0.5);
+}
.itop_popup li a, #logOffBtn li a {
display: block;
padding: 5px 12px;
@@ -2961,56 +2964,137 @@ table.listResults .originColor {
padding-top: 0.3em;
border: none;
}
-/* The switch - the box around the slider */
-.switch {
- position: relative;
- display: inline-block;
- width: 41px;
- height: 23px;
- vertical-align: baseline;
+#newsroom_menu li span {
+ display: block;
+ padding: 5px 12px;
+ text-decoration: none;
+ white-space: nowrap;
}
-/* Hide default HTML checkbox */
-.switch input {
- display: none;
-}
-/* The slider */
-.slider {
- position: absolute;
+#newsroom_menu li li p {
+ text-align: left;
+ margin: 2px;
+ margin-left: 5px;
+ margin-right: 5px;
cursor: pointer;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: #ccc;
- -webkit-transition: 0.4s;
- transition: 0.4s;
+ background-color: transparent;
}
-.slider:before {
- position: absolute;
- content: "";
- height: 17px;
- width: 17px;
+#newsroom_menu > ul > li > ul {
+ margin-top: 8px;
+}
+#newsroom_menu > ul > li > ul > li {
+ display: block;
+ border-bottom: 1px #ddd solid;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ text-align: left;
+}
+#newsroom_menu > ul > li > ul > li:hover, #newsroom_menu > ul > li > ul > li:hover h1, #newsroom_menu > ul > li > ul > li:hover h2, #newsroom_menu > ul > li > ul > li:hover h3 {
+ background: #ea7d1e;
+ color: #fff;
+}
+#newsroom_menu li li:last-of-type {
+ border-bottom: 0;
+}
+#newsroom_menu li {
+ list-style: none;
+ cursor: pointer;
+ color: #000;
+}
+#newsroom_menu li ul {
+ width: 300px;
+}
+#top-left-newsroom-cell {
+ padding-right: 11px !important;
+}
+#newsroom_menu_icon {
+ position: relative;
+ top: 8px;
+}
+#newsroom_menu_counter_container {
+ position: relative;
+ top: -26px;
left: 4px;
bottom: 3px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
-input:checked + .slider {
- background-color: #ea7d1e;
+#newsroom_menu_counter {
+ display: inline-block;
+ padding: 2px;
+ border-radius: 8px;
+ text-align: center;
+ width: 12px;
+ box-shadow: 1px 1px 2px 0px #777;
+ font-size: 8pt;
+ background-color: #1c94c4;
+ color: #fff;
}
-input:focus + .slider {
- box-shadow: 0 0 1px #ea7d1e;
+.newsroom_extra_messages_counter {
+ display: inline-block !important;
+ padding: 2px !important;
+ border-radius: 8px;
+ text-align: center;
+ font-size: 8pt;
+ min-width: 12px;
+ background-color: #808080;
+ color: #fff;
+ float: right;
+ margin-right: 5px;
}
-input:checked + .slider:before {
- -webkit-transform: translateX(16px);
- -ms-transform: translateX(16px);
- transform: translateX(16px);
+.newsroom_menu_item > div > img {
+ float: left;
+ width: 32px;
+ max-height: 32px;
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 5px;
+ margin-right: 5px;
}
-/* Rounded sliders */
-.slider.round {
- border-radius: 34px;
+#newsroom_menu_dismiss_all, #newsroom_menu_show_all {
+ text-align: center !important;
}
-.slider.round:before {
- border-radius: 50%;
+#newsroom_show_all_submenu {
+ text-align: center;
+ padding-top: 0 !important;
+ padding-bottom: 0 !important;
+}
+#newsroom_show_all_submenu > ul {
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
+#newsroom_show_all_submenu > ul > li > ul {
+ margin-top: 8px;
+}
+#newsroom_show_all_submenu > ul > li > ul > li {
+ display: block;
+ border-bottom: 1px #ddd solid;
+ padding-left: 5px;
+ padding-top: 4px;
+ padding-bottom: 6px;
+ text-align: left;
+}
+#newsroom_show_all_submenu > ul > li > ul > li:hover {
+ background: #ea7d1e;
+ color: #fff;
+}
+#newsroom_show_all_submenu li ul {
+ width: 200px;
+ color: #000;
+}
+.no-padding {
+ padding: 0 !important;
+}
+.newsroom_menu_item_date {
+ padding: 0 !important;
+ margin-bottom: -10px;
+ font-size: 8pt;
+ text-align: right;
+ margin-top: -2px;
+ margin-right: 5px;
+ color: #fff;
+}
+#newsroom_display_size {
+ height: 1em;
+ width: 3em;
}
diff --git a/css/light-grey.scss b/css/light-grey.scss
index 5b2823759..691b8ffc6 100644
--- a/css/light-grey.scss
+++ b/css/light-grey.scss
@@ -628,7 +628,9 @@ div.actions_menu > ul > li {
padding: 0;
height: 25px;
}
-
+.itop_popup > ul > li > ul, #logOffBtn > ul > li > ul {
+ box-shadow: 3px 3px 5px 0px rgba(0,0,0,0.5);
+}
.itop_popup li a, #logOffBtn li a {
display: block;
padding: 5px 12px;
@@ -3496,4 +3498,139 @@ input:checked + .slider:before {
.slider.round:before {
border-radius: 50%;
-}
\ No newline at end of file
+}
+
+///////////////////////////
+// Newsroom menu
+
+#newsroom_menu li span {
+ display: block;
+ padding: 5px 12px;
+ text-decoration: none;
+ white-space: nowrap;
+}
+
+#newsroom_menu li li p {
+ text-align: left;
+ margin: 2px;
+ margin-left: 5px;
+ margin-right: 5px;
+ cursor: pointer;
+ background-color: transparent;
+}
+#newsroom_menu > ul > li > ul {
+ margin-top: 8px;
+}
+#newsroom_menu > ul > li > ul > li {
+ display: block;
+ border-bottom: 1px #ddd solid;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ text-align: left;
+}
+#newsroom_menu > ul > li > ul > li:hover, #newsroom_menu > ul > li > ul > li:hover h1, #newsroom_menu > ul > li > ul > li:hover h2, #newsroom_menu > ul > li > ul > li:hover h3 {
+ background: $popup-menu-highlight-color;
+ color: $popup-menu-text-higlight-color;
+}
+#newsroom_menu li li:last-of-type {
+ border-bottom: 0;
+}
+#newsroom_menu li {
+ list-style: none;
+ cursor: pointer;
+ color: $popup-menu-text-color;
+}
+#newsroom_menu li ul {
+ width: 300px;
+}
+#top-left-newsroom-cell {
+ padding-right: 11px !important;
+}
+#newsroom_menu_icon {
+ position:relative;
+ top:8px;
+}
+#newsroom_menu_counter_container {
+ position:relative;
+ top:-26px;
+ left:4px;
+}
+#newsroom_menu_counter {
+ display:inline-block;
+ padding:2px;
+ border-radius:8px;
+ text-align:center;
+ width: 12px;
+ box-shadow: 1px 1px 2px 0px $gray;
+ font-size: 8pt;
+ background-color:$complement-color;
+ color: $white;
+}
+.newsroom_extra_messages_counter {
+ display:inline-block !important;
+ padding:2px !important;
+ border-radius:8px;
+ text-align:center;
+ font-size: 8pt;
+ min-width: 12px;
+ background-color:$gray-light;
+ color: $white;
+ float: right;
+ margin-right: 5px;
+}
+.newsroom_menu_item > div > img {
+ float:left;
+ width:32px;
+ max-height:32px;
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left:5px;
+ margin-right: 5px;
+}
+#newsroom_menu_dismiss_all, #newsroom_menu_show_all {
+ text-align: center !important;
+}
+#newsroom_show_all_submenu {
+ text-align: center;
+ padding-top: 0 !important;
+ padding-bottom: 0 !important;
+}
+#newsroom_show_all_submenu > ul {
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
+#newsroom_show_all_submenu > ul > li > ul {
+ margin-top: 8px;
+}
+#newsroom_show_all_submenu > ul > li > ul > li {
+ display: block;
+ border-bottom: 1px #ddd solid;
+ padding-left: 5px;
+ padding-top: 4px;
+ padding-bottom: 6px;
+ text-align: left;
+}
+#newsroom_show_all_submenu > ul > li > ul > li:hover {
+ background: $popup-menu-highlight-color;
+ color: $popup-menu-text-higlight-color;
+}
+#newsroom_show_all_submenu li ul {
+ width: 200px;
+ color:#000;
+}
+.no-padding {
+ padding: 0 !important;
+}
+.newsroom_menu_item_date {
+ padding: 0 !important;
+ margin-bottom: -10px;
+ font-size: 8pt;
+ text-align: right;
+ margin-top: -2px;
+ margin-right: 5px;
+ color: $white;
+}
+#newsroom_display_size {
+ height: 1em;
+ width: 3em;
+}
diff --git a/datamodels/2.x/itop-hub-connector/css/hub.css b/datamodels/2.x/itop-hub-connector/css/hub.css
index f2defdb4a..5660cacef 100644
--- a/datamodels/2.x/itop-hub-connector/css/hub.css
+++ b/datamodels/2.x/itop-hub-connector/css/hub.css
@@ -1,46 +1,3 @@
-#hub_popup_menu li span {
- display: block;
- padding: 5px 12px;
- text-decoration: none;
- nowidth: 70px;
- white-space: nowrap;
-}
-
-#hub_popup_menu li li p {
- text-align: left;
- margin: 2px;
- margin-left: 5px;
- margin-right: 5px;
- cursor: pointer;
- background-color: transparent;
- color: #000;
-}
-#hub_popup_menu > ul > li > ul {
- margin-top: 8px;
-}
-#hub_popup_menu > ul > li > ul > li {
- display: block;
- border-bottom: 1px #ddd solid;
- padding-top: 10px;
- padding-bottom: 10px;
-}
-#hub_popup_menu > ul > li > ul > li:hover {
- color: #fff;
- background-color: #E87C1E;
-}
-#hub_popup_menu li li:last-of-type {
- border-bottom: 0;
-}
-#hub_popup_menu li {
- list-style: none;
- cursor: pointer;
-}
-#hub_popup_menu li ul {
- width: 340px;
-}
-#top-left-hub-cell {
- padding-right: 8px !important;
-}
#hub_launch_container {
padding:10px;
overflow: visible;
@@ -209,7 +166,7 @@
#hub_launch_content {
width: 100%;
}
-button {
+#hub_launch_content button {
cursor: pointer;
font-weight: bold;
box-shadow: 0px 0px 0px 1px transparent inset, 0px 0em 0px 0px rgba(34, 36, 38, 0.15) inset;
@@ -219,27 +176,27 @@ button {
vertical-align: middle;
padding: 0;
}
-button.positive {
+#hub_launch_content button.positive {
background-color: rgb(234, 125, 30);
color: #FFFFFF;
}
-button:disabled, button[disabled] {
+#hub_launch_content button:disabled, button[disabled] {
background-color: #828487!important;
cursor: progress !important;
}
-button > span {
+#hub_launch_content button > span {
display: inline-block;
padding: 0.8em;
padding-left: 1.3em;
padding-right: 1.3em;
}
-button:hover {
+#hub_launch_content button:hover {
background-color: #D0D0D0;
}
-button.positive:hover {
+#hub_launch_content button.positive:hover {
background-color: rgb(221, 113, 27);
}
-button > img {
+#hub_launch_content button > img {
width: 16px;
height: 16px;
vertical-align: middle;
@@ -249,4 +206,4 @@ button > img {
.horiz-spacer {
display: inline-block;
width: 1.5em;
-}
\ No newline at end of file
+}
diff --git a/datamodels/2.x/itop-hub-connector/datamodel.itop-hub-connector.xml b/datamodels/2.x/itop-hub-connector/datamodel.itop-hub-connector.xml
index 46e44f66b..c3db39615 100644
--- a/datamodels/2.x/itop-hub-connector/datamodel.itop-hub-connector.xml
+++ b/datamodels/2.x/itop-hub-connector/datamodel.itop-hub-connector.xml
@@ -17,7 +17,9 @@
https://www.itophub.io
/my-instances/landing-from-remote
/stateless-remote-itop/landing-from-remote-stateless
- /api/notifications
+ /api/notifications
+ /api/notifications/mark_all_as_read
+ /api/notifications/view_all_messages
../pages/exec.php?exec_module=itop-hub-connector&exec_page=launch.php&target=inform_after_setup
diff --git a/datamodels/2.x/itop-hub-connector/hubnewsroomprovider.class.inc.php b/datamodels/2.x/itop-hub-connector/hubnewsroomprovider.class.inc.php
new file mode 100644
index 000000000..606067e73
--- /dev/null
+++ b/datamodels/2.x/itop-hub-connector/hubnewsroomprovider.class.inc.php
@@ -0,0 +1,74 @@
+MakeURL('route_mark_all_messages_as_read');
+ }
+
+ public function GetFetchURL()
+ {
+ return $this->MakeURL('route_fetch_unread_messages');
+ }
+
+ public function GetViewAllURL()
+ {
+ return $this->MakeURL('route_view_all_messages');
+ }
+ /**
+ * {@inheritDoc}
+ * @see NewsroomProviderBase::GetPreferencesUrl()
+ */
+ public function GetPreferencesUrl()
+ {
+ return null;
+ }
+
+ private function MakeURL($sRouteCode)
+ {
+ $sBaseUrl = $this->oConfig->GetModuleSetting('itop-hub-connector', 'url').MetaModel::GetModuleSetting('itop-hub-connector', $sRouteCode);
+
+ $sParameters = 'uuid[bdd]='.urlencode((string) trim(DBProperty::GetProperty('database_uuid', ''), '{}'));
+ $sParameters .= '&uuid[file]='.urlencode((string) trim(@file_get_contents(APPROOT."data/instance.txt"), "{} \n"));
+ $sParameters .= '&uuid[user]='.urlencode(UserRights::GetUserId());
+
+ return $sBaseUrl.'?'.$sParameters;
+ }
+}
diff --git a/datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php b/datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
index 846684d72..4258fa7b3 100644
--- a/datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
+++ b/datamodels/2.x/itop-hub-connector/module.itop-hub-connector.php
@@ -24,7 +24,8 @@ SetupWebPage::AddModule(
//
'datamodel' => array(
'menus.php',
- 'model.itop-hub-connector.php'
+ 'hubnewsroomprovider.class.inc.php',
+ 'model.itop-hub-connector.php'
),
'webservice' => array(
diff --git a/dictionaries/de.dictionary.itop.ui.php b/dictionaries/de.dictionary.itop.ui.php
index c9807972f..a764c3a38 100644
--- a/dictionaries/de.dictionary.itop.ui.php
+++ b/dictionaries/de.dictionary.itop.ui.php
@@ -1529,3 +1529,17 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Expression:Verb:NOW' => 'jetzt',
'Expression:Verb:ISNULL' => ': nicht definiert',
));
+
+//
+// iTop Newsroom menu
+//
+Dict::Add('DE DE', 'German', 'Deutsch', array(
+ 'UI:Newsroom:NoNewMessage' => 'Keine neue Nachricht',
+ 'UI:Newsroom:MarkAllAsRead' => 'Alle Nachrichten als gelesen markieren',
+ 'UI:Newsroom:ViewAllMessages' => 'Alle Nachrichten anzeigen',
+ 'UI:Newsroom:Preferences' => 'Newsroom-Einstellungen',
+ 'UI:Newsroom:ConfigurationLink' => 'Konfiguration',
+ 'UI:Newsroom:ResetCache' => 'Cache zurücksetzen',
+ 'UI:Newsroom:DisplayMessagesFor_Provider' => 'Nachrichten von %1$s anzeigen',
+ 'UI:Newsroom:DisplayAtMost_X_Messages' => 'Zeigen Sie höchstens %1$s Beiträge im Menü (%2$s) an.',
+));
diff --git a/dictionaries/en.dictionary.itop.ui.php b/dictionaries/en.dictionary.itop.ui.php
index f7ed54807..b45e0215b 100644
--- a/dictionaries/en.dictionary.itop.ui.php
+++ b/dictionaries/en.dictionary.itop.ui.php
@@ -1550,3 +1550,17 @@ Dict::Add('EN US', 'English', 'English', array(
'Expression:Verb:NOW' => 'now',
'Expression:Verb:ISNULL' => ': undefined',
));
+
+//
+// iTop Newsroom menu
+//
+Dict::Add('EN US', 'English', 'English', array(
+ 'UI:Newsroom:NoNewMessage' => 'No new message',
+ 'UI:Newsroom:MarkAllAsRead' => 'Mark all as messages read',
+ 'UI:Newsroom:ViewAllMessages' => 'View all messages',
+ 'UI:Newsroom:Preferences' => 'Newsroom preferences',
+ 'UI:Newsroom:ConfigurationLink' => 'Configuration',
+ 'UI:Newsroom:ResetCache' => 'Reset cache',
+ 'UI:Newsroom:DisplayMessagesFor_Provider' => 'Display messages from %1$s',
+ 'UI:Newsroom:DisplayAtMost_X_Messages' => 'Display up to %1$s messages in the %2$s menu.',
+));
diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php
index 38e91f291..7ee3f4bff 100644
--- a/dictionaries/fr.dictionary.itop.ui.php
+++ b/dictionaries/fr.dictionary.itop.ui.php
@@ -1530,3 +1530,17 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Expression:Verb:NOW' => 'maintenant',
'Expression:Verb:ISNULL' => ' : non défini',
));
+
+//
+// iTop Newsroom menu
+//
+Dict::Add('FR FR', 'French', 'Français', array(
+ 'UI:Newsroom:NoNewMessage' => 'Aucun nouveau message',
+ 'UI:Newsroom:MarkAllAsRead' => 'Marquer tous les messages comme lus',
+ 'UI:Newsroom:ViewAllMessages' => 'Voir tous les messages',
+ 'UI:Newsroom:Preferences' => 'Préférences du centre d\'information',
+ 'UI:Newsroom:ConfigurationLink' => 'Configuration',
+ 'UI:Newsroom:ResetCache' => 'Ràz du cache',
+ 'UI:Newsroom:DisplayMessagesFor_Provider' => 'Afficher les messages de %1$s',
+ 'UI:Newsroom:DisplayAtMost_X_Messages' => 'Afficher au plus %1$s messages dans le menu %2$s.',
+));
diff --git a/dictionaries/nl.dictionary.itop.ui.php b/dictionaries/nl.dictionary.itop.ui.php
index 27377b33b..500179d2a 100644
--- a/dictionaries/nl.dictionary.itop.ui.php
+++ b/dictionaries/nl.dictionary.itop.ui.php
@@ -1549,3 +1549,17 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Expression:Verb:NOW' => 'nu',
'Expression:Verb:ISNULL' => ': ongedefinieerd (NULL)',
));
+
+//
+// iTop Newsroom menu
+//
+Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
+ 'UI:Newsroom:NoNewMessage' => 'Geen nieuw bericht',
+ 'UI:Newsroom:MarkAllAsRead' => 'Markeer alle berichten als gelezen',
+ 'UI:Newsroom:ViewAllMessages' => 'Bekijk alle berichten',
+ 'UI:Newsroom:Preferences' => 'Newsroom preferences',
+ 'UI:Newsroom:ConfigurationLink' => 'Configuratie',
+ 'UI:Newsroom:ResetCache' => 'Reset cache',
+ 'UI:Newsroom:DisplayMessagesFor_Provider' => 'Bekijk berichten van %1$s',
+ 'UI:Newsroom:DisplayAtMost_X_Messages' => 'Toon maximaal %1$s berichten in het %2$s menu.',
+));
diff --git a/dictionaries/ru.dictionary.itop.ui.php b/dictionaries/ru.dictionary.itop.ui.php
index 961c01367..d982eb2ad 100644
--- a/dictionaries/ru.dictionary.itop.ui.php
+++ b/dictionaries/ru.dictionary.itop.ui.php
@@ -1521,3 +1521,17 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Expression:Verb:NOW' => 'now',
'Expression:Verb:ISNULL' => ': undefined~~',
));
+
+//
+// iTop Newsroom menu
+//
+Dict::Add('RU RU', 'Russian', 'Русский', array(
+ 'UI:Newsroom:NoNewMessage' => 'Нет новых сообщений',
+ 'UI:Newsroom:MarkAllAsRead' => 'Отметить все как прочитанные сообщения',
+ 'UI:Newsroom:ViewAllMessages' => 'Посмотреть все сообщения',
+ 'UI:Newsroom:Preferences' => 'Настройки новостей',
+ 'UI:Newsroom:ConfigurationLink' => 'конфигурация',
+ 'UI:Newsroom:ResetCache' => 'Сбросить кеш',
+ 'UI:Newsroom:DisplayMessagesFor_Provider' => 'Показать сообщения от %1$s',
+ 'UI:Newsroom:DisplayAtMost_X_Messages' => 'Отобразите не более %1$s сообщений в меню %2$s.',
+));
diff --git a/images/newsroom_menu.png b/images/newsroom_menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1958055e552ce47e3f71d937a1902df164d67fb
GIT binary patch
literal 302
zcmeAS@N?(olHy`uVBq!ia0vp^azHG~!3HD)zsDs4DYhhUcNc~i3^fdLZp^dIfFhg)
z9+AZi4BWyX%*Zfnjs#GUy~NYkmHiPnuYjohmdcGKK%w29E{-7{$CDEz6b^W-IV5gc
zRIttEwDPUUo*Y3vhfZdRi#n^*6B05MF0WzhoaWxE6792asY>*@mNlJRnQa-yGuX63
zjRj{<$Vf7@67YyQs4!tiQ- msg2.priority) return 1;
+ var oDate1 = new Date(msg1.start_date);
+ var oDate2 = new Date(msg2.start_date);
+ if (oDate1 > oDate2) return -1;
+ if (oDate1 < oDate2) return 1;
+ return 1;
+ });
+
+ this._buildMenu(aAllMessages);
+ },
+ _buildMenu: function(aAllMessages)
+ {
+ var me = this;
+ var iTotalCount = aAllMessages.length;
+ var iCount = 0;
+ var sHtml = '';
+ }
+ if (iCount > 0)
+ {
+ sHtml += '';
+ $(this.element).html(sHtml);
+ var me = this;
+ $('#newsroom_menu > ul').popupmenu();
+ $('.newsroom_menu_item[data-msg-id]').on('click', function(ev) { me._handleClick(this); });
+ $('#newsroom_menu_dismiss_all').on('click', function(ev) { me._markAllAsRead(); });
+ if (this.options.providers.length == 1)
+ {
+ $('#newsroom_menu_show_all').on('click', function(ev) { window.open(me.options.providers[0].view_all_url, '_blank'); });
+ }
+ else
+ {
+ $('#newsroom_show_all_submenu > ul').popupmenu();
+ $('.newsroom_sub_menu_item').on('click', function() { var idx = parseInt($(this).attr('data-provider-id'), 10); window.open(me.options.providers[idx].view_all_url, '_blank');});
+ }
+ }
+ else
+ {
+ $('#top-left-newsroom-cell > img').css({opacity: 0.4}).attr('title', this.options.labels.no_message);
+ }
+
+ },
+ _handleClick: function(elem)
+ {
+ var idxProvider = $(elem).attr('data-provider-id');
+ var msgId = $(elem).attr('data-msg-id');
+ var sUrl = $(elem).attr('data-url');
+
+ this._markOneMessageAsRead(idxProvider, msgId);
+ window.open(sUrl, '_blank');
+ $('#newsroom_menu').remove();
+ $('#newsroom_menu_counter_container').remove();
+ this._getAllMessages();
+ },
+ _resetUnseenCount: function()
+ {
+ var display = $('#newsroom_menu_counter').css('display');
+ $('#newsroom_menu_counter').fadeOut(500, function() {
+ $(this).css('visibility', 'hidden');
+ $(this).css('display', display);
+ });
+ },
+ clearCache: function(idx)
+ {
+ if (idx == undefined)
+ {
+ for(var k in this.options.providers)
+ {
+ var sKey = this._makeCacheKey(k);
+ localStorage.removeItem(sKey);
+ }
+ }
+ else
+ {
+ var sKey = this._makeCacheKey(idx);
+ localStorage.removeItem(sKey);
+ }
+ },
+ _makeCacheKey: function(idxProvider)
+ {
+ return this.options.cache_uuid+'_'+idxProvider;
+ },
+ _cacheData: function(idxProvider, oJSONData)
+ {
+ var sKey = this._makeCacheKey(idxProvider);
+ var bSuccess = true;
+ var oNow = new Date();
+ var oExpirationDate = new Date(oNow.getTime() + this.options.providers[idxProvider].ttl * 1000);
+
+ var oData = {value: JSON.stringify(oJSONData), expiration_date: oExpirationDate.getTime() };
+ try
+ {
+ localStorage.setItem(sKey, JSON.stringify(oData))
+ }
+ catch(e)
+ {
+ console.warn('Newsroom: Failed to store newsroom messages into local storage !! reason: '+e);
+ bSuccess = false;
+ }
+ return bSuccess;
+ },
+ _getCachedData: function(idxProvider)
+ {
+ var sKey = this._makeCacheKey(idxProvider);
+ var sData = localStorage.getItem(sKey);
+ if (sData == null) return null; // No entry in the local storage cache
+ try
+ {
+ var oData = JSON.parse(sData);
+ var oExpiration = new Date(oData.expiration_date);
+ var oNow = new Date();
+ if (oExpiration < oNow)
+ {
+ return null;
+ }
+ return JSON.parse(oData.value);
+ }
+ catch(e)
+ {
+ console.warn('Newsroom: Failed to fetch newsroom messages from local storage !! reason: '+e);
+ this.clearCache(idxProvider);
+ return null;
+ }
+ },
+ _markOneMessageAsRead: function(idxProvider, msgId)
+ {
+ // Remove the given message from the cache
+ var aData = this._getCachedData(idxProvider);
+ if (aData !== null)
+ {
+ var aRemainingData = [];
+ for(var k in aData)
+ {
+ var sId = aData[k].id.toString();
+ if(sId !== msgId)
+ {
+ aRemainingData.push(aData[k]);
+ }
+ }
+ this._cacheData(idxProvider, aRemainingData); // Also extends the TTL of the cache
+ }
+ },
+ _markAllMessagesAsRead: function(idxProvider)
+ {
+ this._cacheData(idxProvider, []); //Store an empty list in the cache
+
+ $.ajax({ type: "GET",
+ url: this.options.providers[idxProvider].mark_all_as_read_url,
+ async: true,
+ dataType : 'jsonp',
+ crossDomain: true,
+ jsonp: "callback"
+ })
+ .done(function(oJSONData) {
+ });
+
+
+ },
+ _markAllAsRead: function()
+ {
+ for(var k in this.options.providers)
+ {
+ this._markAllMessagesAsRead(k);
+ }
+ $('#newsroom_menu').html('
');
+ $('#newsroom_menu_counter_container').remove();
+ this._getAllMessages();
+ }
+ });
+});
diff --git a/js/showdown.min.js b/js/showdown.min.js
new file mode 100644
index 000000000..1249df5c8
--- /dev/null
+++ b/js/showdown.min.js
@@ -0,0 +1,3 @@
+/*! showdown v 2.0.0-alpha1 - 25-09-2018 */
+(function(){function a(e){"use strict";var r={omitExtraWLInCodeBlocks:{defaultValue:!1,describe:"Omit the default extra whiteline added to code blocks",type:"boolean"},noHeaderId:{defaultValue:!1,describe:"Turn on/off generated header id",type:"boolean"},prefixHeaderId:{defaultValue:!1,describe:"Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic 'section-' prefix",type:"string"},rawPrefixHeaderId:{defaultValue:!1,describe:'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',type:"boolean"},ghCompatibleHeaderId:{defaultValue:!1,describe:"Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)",type:"boolean"},rawHeaderId:{defaultValue:!1,describe:"Remove only spaces, ' and \" from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids",type:"boolean"},headerLevelStart:{defaultValue:!1,describe:"The header blocks level start",type:"integer"},parseImgDimensions:{defaultValue:!1,describe:"Turn on/off image dimension parsing",type:"boolean"},simplifiedAutoLink:{defaultValue:!1,describe:"Turn on/off GFM autolink style",type:"boolean"},literalMidWordUnderscores:{defaultValue:!1,describe:"Parse midword underscores as literal underscores",type:"boolean"},literalMidWordAsterisks:{defaultValue:!1,describe:"Parse midword asterisks as literal asterisks",type:"boolean"},strikethrough:{defaultValue:!1,describe:"Turn on/off strikethrough support",type:"boolean"},tables:{defaultValue:!1,describe:"Turn on/off tables support",type:"boolean"},tablesHeaderId:{defaultValue:!1,describe:"Add an id to table headers",type:"boolean"},ghCodeBlocks:{defaultValue:!0,describe:"Turn on/off GFM fenced code blocks support",type:"boolean"},tasklists:{defaultValue:!1,describe:"Turn on/off GFM tasklist support",type:"boolean"},smoothLivePreview:{defaultValue:!1,describe:"Prevents weird effects in live previews due to incomplete input",type:"boolean"},smartIndentationFix:{defaultValue:!1,description:"Tries to smartly fix indentation in es6 strings",type:"boolean"},disableForced4SpacesIndentedSublists:{defaultValue:!1,description:"Disables the requirement of indenting nested sublists by 4 spaces",type:"boolean"},simpleLineBreaks:{defaultValue:!1,description:"Parses simple line breaks as
(GFM Style)",type:"boolean"},requireSpaceBeforeHeadingText:{defaultValue:!1,description:"Makes adding a space between `#` and the header text mandatory (GFM Style)",type:"boolean"},ghMentions:{defaultValue:!1,description:"Enables github @mentions",type:"boolean"},ghMentionsLink:{defaultValue:"https://github.com/{u}",description:"Changes the link generated by @mentions. Only applies if ghMentions option is enabled.",type:"string"},encodeEmails:{defaultValue:!0,description:"Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities",type:"boolean"},openLinksInNewWindow:{defaultValue:!1,description:"Open all links in new windows",type:"boolean"},backslashEscapesHTMLTags:{defaultValue:!1,description:"Support for HTML Tag escaping. ex: foo
",type:"boolean"},emoji:{defaultValue:!1,description:"Enable emoji support. Ex: `this is a :smile: emoji`",type:"boolean"},underline:{defaultValue:!1,description:"Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `` and ``",type:"boolean"},completeHTMLDocument:{defaultValue:!1,description:"Outputs a complete html document, including ``, `` and `` tags",type:"boolean"},metadata:{defaultValue:!1,description:"Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).",type:"boolean"},splitAdjacentBlockquotes:{defaultValue:!1,description:"Split adjacent blockquote blocks",type:"boolean"}};if(!1===e)return JSON.parse(JSON.stringify(r));var t={};for(var a in r)r.hasOwnProperty(a)&&(t[a]=r[a].defaultValue);return t}var b={},t={},h={},m=a(!0),d="vanilla",p={github:{omitExtraWLInCodeBlocks:!0,simplifiedAutoLink:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,disableForced4SpacesIndentedSublists:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghCompatibleHeaderId:!0,ghMentions:!0,backslashEscapesHTMLTags:!0,emoji:!0,splitAdjacentBlockquotes:!0},original:{noHeaderId:!0,ghCodeBlocks:!1},ghost:{omitExtraWLInCodeBlocks:!0,parseImgDimensions:!0,simplifiedAutoLink:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,smoothLivePreview:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghMentions:!1,encodeEmails:!0},vanilla:a(!0),allOn:function(){"use strict";var e=a(!0),r={};for(var t in e)e.hasOwnProperty(t)&&(r[t]=!0);return r}()};function g(e,r){"use strict";var t=r?"Error in "+r+" extension->":"Error in unnamed extension",a={valid:!0,error:""};b.helper.isArray(e)||(e=[e]);for(var n=0;n>=0,t=String(t||" "),e.length>r?String(e):((r-=e.length)>t.length&&(t+=t.repeat(r/t.length)),String(e)+t.slice(0,r))},b.helper.unescapeHTMLEntities=function(e){"use strict";return e.replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&")},b.helper._hashHTMLSpan=function(e,r){return"¨C"+(r.gHtmlSpans.push(e)-1)+"C"},b.helper.Event=function(e,r,t){"use strict";var a=t.regexp||null,n=t.matches||{},s=t.options||{},o=t.converter||null,i=t.globals||{};this.getName=function(){return e},this.getEventName=function(){return e},this._stopExecution=!1,this.parsedText=t.parsedText||null,this.getRegexp=function(){return a},this.getOptions=function(){return s},this.getConverter=function(){return o},this.getGlobals=function(){return i},this.getCapturedText=function(){return r},this.getText=function(){return r},this.setText=function(e){r=e},this.getMatches=function(){return n},this.setMatches=function(e){n=e},this.preventDefault=function(e){this._stopExecution=!e}},"undefined"==typeof console&&(console={warn:function(e){"use strict";alert(e)},log:function(e){"use strict";alert(e)},error:function(e){"use strict";throw e}}),b.helper.regexes={asteriskDashTildeAndColon:/([*_:~])/g,asteriskDashAndTilde:/([*_~])/g},b.helper.emojis={"+1":"👍","-1":"👎",100:"💯",1234:"🔢","1st_place_medal":"🥇","2nd_place_medal":"🥈","3rd_place_medal":"🥉","8ball":"🎱",a:"🅰️",ab:"🆎",abc:"🔤",abcd:"🔡",accept:"🉑",aerial_tramway:"🚡",airplane:"✈️",alarm_clock:"⏰",alembic:"⚗️",alien:"👽",ambulance:"🚑",amphora:"🏺",anchor:"⚓️",angel:"👼",anger:"💢",angry:"😠",anguished:"😧",ant:"🐜",apple:"🍎",aquarius:"♒️",aries:"♈️",arrow_backward:"◀️",arrow_double_down:"⏬",arrow_double_up:"⏫",arrow_down:"⬇️",arrow_down_small:"🔽",arrow_forward:"▶️",arrow_heading_down:"⤵️",arrow_heading_up:"⤴️",arrow_left:"⬅️",arrow_lower_left:"↙️",arrow_lower_right:"↘️",arrow_right:"➡️",arrow_right_hook:"↪️",arrow_up:"⬆️",arrow_up_down:"↕️",arrow_up_small:"🔼",arrow_upper_left:"↖️",arrow_upper_right:"↗️",arrows_clockwise:"🔃",arrows_counterclockwise:"🔄",art:"🎨",articulated_lorry:"🚛",artificial_satellite:"🛰",astonished:"😲",athletic_shoe:"👟",atm:"🏧",atom_symbol:"⚛️",avocado:"🥑",b:"🅱️",baby:"👶",baby_bottle:"🍼",baby_chick:"🐤",baby_symbol:"🚼",back:"🔙",bacon:"🥓",badminton:"🏸",baggage_claim:"🛄",baguette_bread:"🥖",balance_scale:"⚖️",balloon:"🎈",ballot_box:"🗳",ballot_box_with_check:"☑️",bamboo:"🎍",banana:"🍌",bangbang:"‼️",bank:"🏦",bar_chart:"📊",barber:"💈",baseball:"⚾️",basketball:"🏀",basketball_man:"⛹️",basketball_woman:"⛹️♀️",bat:"🦇",bath:"🛀",bathtub:"🛁",battery:"🔋",beach_umbrella:"🏖",bear:"🐻",bed:"🛏",bee:"🐝",beer:"🍺",beers:"🍻",beetle:"🐞",beginner:"🔰",bell:"🔔",bellhop_bell:"🛎",bento:"🍱",biking_man:"🚴",bike:"🚲",biking_woman:"🚴♀️",bikini:"👙",biohazard:"☣️",bird:"🐦",birthday:"🎂",black_circle:"⚫️",black_flag:"🏴",black_heart:"🖤",black_joker:"🃏",black_large_square:"⬛️",black_medium_small_square:"◾️",black_medium_square:"◼️",black_nib:"✒️",black_small_square:"▪️",black_square_button:"🔲",blonde_man:"👱",blonde_woman:"👱♀️",blossom:"🌼",blowfish:"🐡",blue_book:"📘",blue_car:"🚙",blue_heart:"💙",blush:"😊",boar:"🐗",boat:"⛵️",bomb:"💣",book:"📖",bookmark:"🔖",bookmark_tabs:"📑",books:"📚",boom:"💥",boot:"👢",bouquet:"💐",bowing_man:"🙇",bow_and_arrow:"🏹",bowing_woman:"🙇♀️",bowling:"🎳",boxing_glove:"🥊",boy:"👦",bread:"🍞",bride_with_veil:"👰",bridge_at_night:"🌉",briefcase:"💼",broken_heart:"💔",bug:"🐛",building_construction:"🏗",bulb:"💡",bullettrain_front:"🚅",bullettrain_side:"🚄",burrito:"🌯",bus:"🚌",business_suit_levitating:"🕴",busstop:"🚏",bust_in_silhouette:"👤",busts_in_silhouette:"👥",butterfly:"🦋",cactus:"🌵",cake:"🍰",calendar:"📆",call_me_hand:"🤙",calling:"📲",camel:"🐫",camera:"📷",camera_flash:"📸",camping:"🏕",cancer:"♋️",candle:"🕯",candy:"🍬",canoe:"🛶",capital_abcd:"🔠",capricorn:"♑️",car:"🚗",card_file_box:"🗃",card_index:"📇",card_index_dividers:"🗂",carousel_horse:"🎠",carrot:"🥕",cat:"🐱",cat2:"🐈",cd:"💿",chains:"⛓",champagne:"🍾",chart:"💹",chart_with_downwards_trend:"📉",chart_with_upwards_trend:"📈",checkered_flag:"🏁",cheese:"🧀",cherries:"🍒",cherry_blossom:"🌸",chestnut:"🌰",chicken:"🐔",children_crossing:"🚸",chipmunk:"🐿",chocolate_bar:"🍫",christmas_tree:"🎄",church:"⛪️",cinema:"🎦",circus_tent:"🎪",city_sunrise:"🌇",city_sunset:"🌆",cityscape:"🏙",cl:"🆑",clamp:"🗜",clap:"👏",clapper:"🎬",classical_building:"🏛",clinking_glasses:"🥂",clipboard:"📋",clock1:"🕐",clock10:"🕙",clock1030:"🕥",clock11:"🕚",clock1130:"🕦",clock12:"🕛",clock1230:"🕧",clock130:"🕜",clock2:"🕑",clock230:"🕝",clock3:"🕒",clock330:"🕞",clock4:"🕓",clock430:"🕟",clock5:"🕔",clock530:"🕠",clock6:"🕕",clock630:"🕡",clock7:"🕖",clock730:"🕢",clock8:"🕗",clock830:"🕣",clock9:"🕘",clock930:"🕤",closed_book:"📕",closed_lock_with_key:"🔐",closed_umbrella:"🌂",cloud:"☁️",cloud_with_lightning:"🌩",cloud_with_lightning_and_rain:"⛈",cloud_with_rain:"🌧",cloud_with_snow:"🌨",clown_face:"🤡",clubs:"♣️",cocktail:"🍸",coffee:"☕️",coffin:"⚰️",cold_sweat:"😰",comet:"☄️",computer:"💻",computer_mouse:"🖱",confetti_ball:"🎊",confounded:"😖",confused:"😕",congratulations:"㊗️",construction:"🚧",construction_worker_man:"👷",construction_worker_woman:"👷♀️",control_knobs:"🎛",convenience_store:"🏪",cookie:"🍪",cool:"🆒",policeman:"👮",copyright:"©️",corn:"🌽",couch_and_lamp:"🛋",couple:"👫",couple_with_heart_woman_man:"💑",couple_with_heart_man_man:"👨❤️👨",couple_with_heart_woman_woman:"👩❤️👩",couplekiss_man_man:"👨❤️💋👨",couplekiss_man_woman:"💏",couplekiss_woman_woman:"👩❤️💋👩",cow:"🐮",cow2:"🐄",cowboy_hat_face:"🤠",crab:"🦀",crayon:"🖍",credit_card:"💳",crescent_moon:"🌙",cricket:"🏏",crocodile:"🐊",croissant:"🥐",crossed_fingers:"🤞",crossed_flags:"🎌",crossed_swords:"⚔️",crown:"👑",cry:"😢",crying_cat_face:"😿",crystal_ball:"🔮",cucumber:"🥒",cupid:"💘",curly_loop:"➰",currency_exchange:"💱",curry:"🍛",custard:"🍮",customs:"🛃",cyclone:"🌀",dagger:"🗡",dancer:"💃",dancing_women:"👯",dancing_men:"👯♂️",dango:"🍡",dark_sunglasses:"🕶",dart:"🎯",dash:"💨",date:"📅",deciduous_tree:"🌳",deer:"🦌",department_store:"🏬",derelict_house:"🏚",desert:"🏜",desert_island:"🏝",desktop_computer:"🖥",male_detective:"🕵️",diamond_shape_with_a_dot_inside:"💠",diamonds:"♦️",disappointed:"😞",disappointed_relieved:"😥",dizzy:"💫",dizzy_face:"😵",do_not_litter:"🚯",dog:"🐶",dog2:"🐕",dollar:"💵",dolls:"🎎",dolphin:"🐬",door:"🚪",doughnut:"🍩",dove:"🕊",dragon:"🐉",dragon_face:"🐲",dress:"👗",dromedary_camel:"🐪",drooling_face:"🤤",droplet:"💧",drum:"🥁",duck:"🦆",dvd:"📀","e-mail":"📧",eagle:"🦅",ear:"👂",ear_of_rice:"🌾",earth_africa:"🌍",earth_americas:"🌎",earth_asia:"🌏",egg:"🥚",eggplant:"🍆",eight_pointed_black_star:"✴️",eight_spoked_asterisk:"✳️",electric_plug:"🔌",elephant:"🐘",email:"✉️",end:"🔚",envelope_with_arrow:"📩",euro:"💶",european_castle:"🏰",european_post_office:"🏤",evergreen_tree:"🌲",exclamation:"❗️",expressionless:"😑",eye:"👁",eye_speech_bubble:"👁🗨",eyeglasses:"👓",eyes:"👀",face_with_head_bandage:"🤕",face_with_thermometer:"🤒",fist_oncoming:"👊",factory:"🏭",fallen_leaf:"🍂",family_man_woman_boy:"👪",family_man_boy:"👨👦",family_man_boy_boy:"👨👦👦",family_man_girl:"👨👧",family_man_girl_boy:"👨👧👦",family_man_girl_girl:"👨👧👧",family_man_man_boy:"👨👨👦",family_man_man_boy_boy:"👨👨👦👦",family_man_man_girl:"👨👨👧",family_man_man_girl_boy:"👨👨👧👦",family_man_man_girl_girl:"👨👨👧👧",family_man_woman_boy_boy:"👨👩👦👦",family_man_woman_girl:"👨👩👧",family_man_woman_girl_boy:"👨👩👧👦",family_man_woman_girl_girl:"👨👩👧👧",family_woman_boy:"👩👦",family_woman_boy_boy:"👩👦👦",family_woman_girl:"👩👧",family_woman_girl_boy:"👩👧👦",family_woman_girl_girl:"👩👧👧",family_woman_woman_boy:"👩👩👦",family_woman_woman_boy_boy:"👩👩👦👦",family_woman_woman_girl:"👩👩👧",family_woman_woman_girl_boy:"👩👩👧👦",family_woman_woman_girl_girl:"👩👩👧👧",fast_forward:"⏩",fax:"📠",fearful:"😨",feet:"🐾",female_detective:"🕵️♀️",ferris_wheel:"🎡",ferry:"⛴",field_hockey:"🏑",file_cabinet:"🗄",file_folder:"📁",film_projector:"📽",film_strip:"🎞",fire:"🔥",fire_engine:"🚒",fireworks:"🎆",first_quarter_moon:"🌓",first_quarter_moon_with_face:"🌛",fish:"🐟",fish_cake:"🍥",fishing_pole_and_fish:"🎣",fist_raised:"✊",fist_left:"🤛",fist_right:"🤜",flags:"🎏",flashlight:"🔦",fleur_de_lis:"⚜️",flight_arrival:"🛬",flight_departure:"🛫",floppy_disk:"💾",flower_playing_cards:"🎴",flushed:"😳",fog:"🌫",foggy:"🌁",football:"🏈",footprints:"👣",fork_and_knife:"🍴",fountain:"⛲️",fountain_pen:"🖋",four_leaf_clover:"🍀",fox_face:"🦊",framed_picture:"🖼",free:"🆓",fried_egg:"🍳",fried_shrimp:"🍤",fries:"🍟",frog:"🐸",frowning:"😦",frowning_face:"☹️",frowning_man:"🙍♂️",frowning_woman:"🙍",middle_finger:"🖕",fuelpump:"⛽️",full_moon:"🌕",full_moon_with_face:"🌝",funeral_urn:"⚱️",game_die:"🎲",gear:"⚙️",gem:"💎",gemini:"♊️",ghost:"👻",gift:"🎁",gift_heart:"💝",girl:"👧",globe_with_meridians:"🌐",goal_net:"🥅",goat:"🐐",golf:"⛳️",golfing_man:"🏌️",golfing_woman:"🏌️♀️",gorilla:"🦍",grapes:"🍇",green_apple:"🍏",green_book:"📗",green_heart:"💚",green_salad:"🥗",grey_exclamation:"❕",grey_question:"❔",grimacing:"😬",grin:"😁",grinning:"😀",guardsman:"💂",guardswoman:"💂♀️",guitar:"🎸",gun:"🔫",haircut_woman:"💇",haircut_man:"💇♂️",hamburger:"🍔",hammer:"🔨",hammer_and_pick:"⚒",hammer_and_wrench:"🛠",hamster:"🐹",hand:"✋",handbag:"👜",handshake:"🤝",hankey:"💩",hatched_chick:"🐥",hatching_chick:"🐣",headphones:"🎧",hear_no_evil:"🙉",heart:"❤️",heart_decoration:"💟",heart_eyes:"😍",heart_eyes_cat:"😻",heartbeat:"💓",heartpulse:"💗",hearts:"♥️",heavy_check_mark:"✔️",heavy_division_sign:"➗",heavy_dollar_sign:"💲",heavy_heart_exclamation:"❣️",heavy_minus_sign:"➖",heavy_multiplication_x:"✖️",heavy_plus_sign:"➕",helicopter:"🚁",herb:"🌿",hibiscus:"🌺",high_brightness:"🔆",high_heel:"👠",hocho:"🔪",hole:"🕳",honey_pot:"🍯",horse:"🐴",horse_racing:"🏇",hospital:"🏥",hot_pepper:"🌶",hotdog:"🌭",hotel:"🏨",hotsprings:"♨️",hourglass:"⌛️",hourglass_flowing_sand:"⏳",house:"🏠",house_with_garden:"🏡",houses:"🏘",hugs:"🤗",hushed:"😯",ice_cream:"🍨",ice_hockey:"🏒",ice_skate:"⛸",icecream:"🍦",id:"🆔",ideograph_advantage:"🉐",imp:"👿",inbox_tray:"📥",incoming_envelope:"📨",tipping_hand_woman:"💁",information_source:"ℹ️",innocent:"😇",interrobang:"⁉️",iphone:"📱",izakaya_lantern:"🏮",jack_o_lantern:"🎃",japan:"🗾",japanese_castle:"🏯",japanese_goblin:"👺",japanese_ogre:"👹",jeans:"👖",joy:"😂",joy_cat:"😹",joystick:"🕹",kaaba:"🕋",key:"🔑",keyboard:"⌨️",keycap_ten:"🔟",kick_scooter:"🛴",kimono:"👘",kiss:"💋",kissing:"😗",kissing_cat:"😽",kissing_closed_eyes:"😚",kissing_heart:"😘",kissing_smiling_eyes:"😙",kiwi_fruit:"🥝",koala:"🐨",koko:"🈁",label:"🏷",large_blue_circle:"🔵",large_blue_diamond:"🔷",large_orange_diamond:"🔶",last_quarter_moon:"🌗",last_quarter_moon_with_face:"🌜",latin_cross:"✝️",laughing:"😆",leaves:"🍃",ledger:"📒",left_luggage:"🛅",left_right_arrow:"↔️",leftwards_arrow_with_hook:"↩️",lemon:"🍋",leo:"♌️",leopard:"🐆",level_slider:"🎚",libra:"♎️",light_rail:"🚈",link:"🔗",lion:"🦁",lips:"👄",lipstick:"💄",lizard:"🦎",lock:"🔒",lock_with_ink_pen:"🔏",lollipop:"🍭",loop:"➿",loud_sound:"🔊",loudspeaker:"📢",love_hotel:"🏩",love_letter:"💌",low_brightness:"🔅",lying_face:"🤥",m:"Ⓜ️",mag:"🔍",mag_right:"🔎",mahjong:"🀄️",mailbox:"📫",mailbox_closed:"📪",mailbox_with_mail:"📬",mailbox_with_no_mail:"📭",man:"👨",man_artist:"👨🎨",man_astronaut:"👨🚀",man_cartwheeling:"🤸♂️",man_cook:"👨🍳",man_dancing:"🕺",man_facepalming:"🤦♂️",man_factory_worker:"👨🏭",man_farmer:"👨🌾",man_firefighter:"👨🚒",man_health_worker:"👨⚕️",man_in_tuxedo:"🤵",man_judge:"👨⚖️",man_juggling:"🤹♂️",man_mechanic:"👨🔧",man_office_worker:"👨💼",man_pilot:"👨✈️",man_playing_handball:"🤾♂️",man_playing_water_polo:"🤽♂️",man_scientist:"👨🔬",man_shrugging:"🤷♂️",man_singer:"👨🎤",man_student:"👨🎓",man_teacher:"👨🏫",man_technologist:"👨💻",man_with_gua_pi_mao:"👲",man_with_turban:"👳",tangerine:"🍊",mans_shoe:"👞",mantelpiece_clock:"🕰",maple_leaf:"🍁",martial_arts_uniform:"🥋",mask:"😷",massage_woman:"💆",massage_man:"💆♂️",meat_on_bone:"🍖",medal_military:"🎖",medal_sports:"🏅",mega:"📣",melon:"🍈",memo:"📝",men_wrestling:"🤼♂️",menorah:"🕎",mens:"🚹",metal:"🤘",metro:"🚇",microphone:"🎤",microscope:"🔬",milk_glass:"🥛",milky_way:"🌌",minibus:"🚐",minidisc:"💽",mobile_phone_off:"📴",money_mouth_face:"🤑",money_with_wings:"💸",moneybag:"💰",monkey:"🐒",monkey_face:"🐵",monorail:"🚝",moon:"🌔",mortar_board:"🎓",mosque:"🕌",motor_boat:"🛥",motor_scooter:"🛵",motorcycle:"🏍",motorway:"🛣",mount_fuji:"🗻",mountain:"⛰",mountain_biking_man:"🚵",mountain_biking_woman:"🚵♀️",mountain_cableway:"🚠",mountain_railway:"🚞",mountain_snow:"🏔",mouse:"🐭",mouse2:"🐁",movie_camera:"🎥",moyai:"🗿",mrs_claus:"🤶",muscle:"💪",mushroom:"🍄",musical_keyboard:"🎹",musical_note:"🎵",musical_score:"🎼",mute:"🔇",nail_care:"💅",name_badge:"📛",national_park:"🏞",nauseated_face:"🤢",necktie:"👔",negative_squared_cross_mark:"❎",nerd_face:"🤓",neutral_face:"😐",new:"🆕",new_moon:"🌑",new_moon_with_face:"🌚",newspaper:"📰",newspaper_roll:"🗞",next_track_button:"⏭",ng:"🆖",no_good_man:"🙅♂️",no_good_woman:"🙅",night_with_stars:"🌃",no_bell:"🔕",no_bicycles:"🚳",no_entry:"⛔️",no_entry_sign:"🚫",no_mobile_phones:"📵",no_mouth:"😶",no_pedestrians:"🚷",no_smoking:"🚭","non-potable_water":"🚱",nose:"👃",notebook:"📓",notebook_with_decorative_cover:"📔",notes:"🎶",nut_and_bolt:"🔩",o:"⭕️",o2:"🅾️",ocean:"🌊",octopus:"🐙",oden:"🍢",office:"🏢",oil_drum:"🛢",ok:"🆗",ok_hand:"👌",ok_man:"🙆♂️",ok_woman:"🙆",old_key:"🗝",older_man:"👴",older_woman:"👵",om:"🕉",on:"🔛",oncoming_automobile:"🚘",oncoming_bus:"🚍",oncoming_police_car:"🚔",oncoming_taxi:"🚖",open_file_folder:"📂",open_hands:"👐",open_mouth:"😮",open_umbrella:"☂️",ophiuchus:"⛎",orange_book:"📙",orthodox_cross:"☦️",outbox_tray:"📤",owl:"🦉",ox:"🐂",package:"📦",page_facing_up:"📄",page_with_curl:"📃",pager:"📟",paintbrush:"🖌",palm_tree:"🌴",pancakes:"🥞",panda_face:"🐼",paperclip:"📎",paperclips:"🖇",parasol_on_ground:"⛱",parking:"🅿️",part_alternation_mark:"〽️",partly_sunny:"⛅️",passenger_ship:"🛳",passport_control:"🛂",pause_button:"⏸",peace_symbol:"☮️",peach:"🍑",peanuts:"🥜",pear:"🍐",pen:"🖊",pencil2:"✏️",penguin:"🐧",pensive:"😔",performing_arts:"🎭",persevere:"😣",person_fencing:"🤺",pouting_woman:"🙎",phone:"☎️",pick:"⛏",pig:"🐷",pig2:"🐖",pig_nose:"🐽",pill:"💊",pineapple:"🍍",ping_pong:"🏓",pisces:"♓️",pizza:"🍕",place_of_worship:"🛐",plate_with_cutlery:"🍽",play_or_pause_button:"⏯",point_down:"👇",point_left:"👈",point_right:"👉",point_up:"☝️",point_up_2:"👆",police_car:"🚓",policewoman:"👮♀️",poodle:"🐩",popcorn:"🍿",post_office:"🏣",postal_horn:"📯",postbox:"📮",potable_water:"🚰",potato:"🥔",pouch:"👝",poultry_leg:"🍗",pound:"💷",rage:"😡",pouting_cat:"😾",pouting_man:"🙎♂️",pray:"🙏",prayer_beads:"📿",pregnant_woman:"🤰",previous_track_button:"⏮",prince:"🤴",princess:"👸",printer:"🖨",purple_heart:"💜",purse:"👛",pushpin:"📌",put_litter_in_its_place:"🚮",question:"❓",rabbit:"🐰",rabbit2:"🐇",racehorse:"🐎",racing_car:"🏎",radio:"📻",radio_button:"🔘",radioactive:"☢️",railway_car:"🚃",railway_track:"🛤",rainbow:"🌈",rainbow_flag:"🏳️🌈",raised_back_of_hand:"🤚",raised_hand_with_fingers_splayed:"🖐",raised_hands:"🙌",raising_hand_woman:"🙋",raising_hand_man:"🙋♂️",ram:"🐏",ramen:"🍜",rat:"🐀",record_button:"⏺",recycle:"♻️",red_circle:"🔴",registered:"®️",relaxed:"☺️",relieved:"😌",reminder_ribbon:"🎗",repeat:"🔁",repeat_one:"🔂",rescue_worker_helmet:"⛑",restroom:"🚻",revolving_hearts:"💞",rewind:"⏪",rhinoceros:"🦏",ribbon:"🎀",rice:"🍚",rice_ball:"🍙",rice_cracker:"🍘",rice_scene:"🎑",right_anger_bubble:"🗯",ring:"💍",robot:"🤖",rocket:"🚀",rofl:"🤣",roll_eyes:"🙄",roller_coaster:"🎢",rooster:"🐓",rose:"🌹",rosette:"🏵",rotating_light:"🚨",round_pushpin:"📍",rowing_man:"🚣",rowing_woman:"🚣♀️",rugby_football:"🏉",running_man:"🏃",running_shirt_with_sash:"🎽",running_woman:"🏃♀️",sa:"🈂️",sagittarius:"♐️",sake:"🍶",sandal:"👡",santa:"🎅",satellite:"📡",saxophone:"🎷",school:"🏫",school_satchel:"🎒",scissors:"✂️",scorpion:"🦂",scorpius:"♏️",scream:"😱",scream_cat:"🙀",scroll:"📜",seat:"💺",secret:"㊙️",see_no_evil:"🙈",seedling:"🌱",selfie:"🤳",shallow_pan_of_food:"🥘",shamrock:"☘️",shark:"🦈",shaved_ice:"🍧",sheep:"🐑",shell:"🐚",shield:"🛡",shinto_shrine:"⛩",ship:"🚢",shirt:"👕",shopping:"🛍",shopping_cart:"🛒",shower:"🚿",shrimp:"🦐",signal_strength:"📶",six_pointed_star:"🔯",ski:"🎿",skier:"⛷",skull:"💀",skull_and_crossbones:"☠️",sleeping:"😴",sleeping_bed:"🛌",sleepy:"😪",slightly_frowning_face:"🙁",slightly_smiling_face:"🙂",slot_machine:"🎰",small_airplane:"🛩",small_blue_diamond:"🔹",small_orange_diamond:"🔸",small_red_triangle:"🔺",small_red_triangle_down:"🔻",smile:"😄",smile_cat:"😸",smiley:"😃",smiley_cat:"😺",smiling_imp:"😈",smirk:"😏",smirk_cat:"😼",smoking:"🚬",snail:"🐌",snake:"🐍",sneezing_face:"🤧",snowboarder:"🏂",snowflake:"❄️",snowman:"⛄️",snowman_with_snow:"☃️",sob:"😭",soccer:"⚽️",soon:"🔜",sos:"🆘",sound:"🔉",space_invader:"👾",spades:"♠️",spaghetti:"🍝",sparkle:"❇️",sparkler:"🎇",sparkles:"✨",sparkling_heart:"💖",speak_no_evil:"🙊",speaker:"🔈",speaking_head:"🗣",speech_balloon:"💬",speedboat:"🚤",spider:"🕷",spider_web:"🕸",spiral_calendar:"🗓",spiral_notepad:"🗒",spoon:"🥄",squid:"🦑",stadium:"🏟",star:"⭐️",star2:"🌟",star_and_crescent:"☪️",star_of_david:"✡️",stars:"🌠",station:"🚉",statue_of_liberty:"🗽",steam_locomotive:"🚂",stew:"🍲",stop_button:"⏹",stop_sign:"🛑",stopwatch:"⏱",straight_ruler:"📏",strawberry:"🍓",stuck_out_tongue:"😛",stuck_out_tongue_closed_eyes:"😝",stuck_out_tongue_winking_eye:"😜",studio_microphone:"🎙",stuffed_flatbread:"🥙",sun_behind_large_cloud:"🌥",sun_behind_rain_cloud:"🌦",sun_behind_small_cloud:"🌤",sun_with_face:"🌞",sunflower:"🌻",sunglasses:"😎",sunny:"☀️",sunrise:"🌅",sunrise_over_mountains:"🌄",surfing_man:"🏄",surfing_woman:"🏄♀️",sushi:"🍣",suspension_railway:"🚟",sweat:"😓",sweat_drops:"💦",sweat_smile:"😅",sweet_potato:"🍠",swimming_man:"🏊",swimming_woman:"🏊♀️",symbols:"🔣",synagogue:"🕍",syringe:"💉",taco:"🌮",tada:"🎉",tanabata_tree:"🎋",taurus:"♉️",taxi:"🚕",tea:"🍵",telephone_receiver:"📞",telescope:"🔭",tennis:"🎾",tent:"⛺️",thermometer:"🌡",thinking:"🤔",thought_balloon:"💭",ticket:"🎫",tickets:"🎟",tiger:"🐯",tiger2:"🐅",timer_clock:"⏲",tipping_hand_man:"💁♂️",tired_face:"😫",tm:"™️",toilet:"🚽",tokyo_tower:"🗼",tomato:"🍅",tongue:"👅",top:"🔝",tophat:"🎩",tornado:"🌪",trackball:"🖲",tractor:"🚜",traffic_light:"🚥",train:"🚋",train2:"🚆",tram:"🚊",triangular_flag_on_post:"🚩",triangular_ruler:"📐",trident:"🔱",triumph:"😤",trolleybus:"🚎",trophy:"🏆",tropical_drink:"🍹",tropical_fish:"🐠",truck:"🚚",trumpet:"🎺",tulip:"🌷",tumbler_glass:"🥃",turkey:"🦃",turtle:"🐢",tv:"📺",twisted_rightwards_arrows:"🔀",two_hearts:"💕",two_men_holding_hands:"👬",two_women_holding_hands:"👭",u5272:"🈹",u5408:"🈴",u55b6:"🈺",u6307:"🈯️",u6708:"🈷️",u6709:"🈶",u6e80:"🈵",u7121:"🈚️",u7533:"🈸",u7981:"🈲",u7a7a:"🈳",umbrella:"☔️",unamused:"😒",underage:"🔞",unicorn:"🦄",unlock:"🔓",up:"🆙",upside_down_face:"🙃",v:"✌️",vertical_traffic_light:"🚦",vhs:"📼",vibration_mode:"📳",video_camera:"📹",video_game:"🎮",violin:"🎻",virgo:"♍️",volcano:"🌋",volleyball:"🏐",vs:"🆚",vulcan_salute:"🖖",walking_man:"🚶",walking_woman:"🚶♀️",waning_crescent_moon:"🌘",waning_gibbous_moon:"🌖",warning:"⚠️",wastebasket:"🗑",watch:"⌚️",water_buffalo:"🐃",watermelon:"🍉",wave:"👋",wavy_dash:"〰️",waxing_crescent_moon:"🌒",wc:"🚾",weary:"😩",wedding:"💒",weight_lifting_man:"🏋️",weight_lifting_woman:"🏋️♀️",whale:"🐳",whale2:"🐋",wheel_of_dharma:"☸️",wheelchair:"♿️",white_check_mark:"✅",white_circle:"⚪️",white_flag:"🏳️",white_flower:"💮",white_large_square:"⬜️",white_medium_small_square:"◽️",white_medium_square:"◻️",white_small_square:"▫️",white_square_button:"🔳",wilted_flower:"🥀",wind_chime:"🎐",wind_face:"🌬",wine_glass:"🍷",wink:"😉",wolf:"🐺",woman:"👩",woman_artist:"👩🎨",woman_astronaut:"👩🚀",woman_cartwheeling:"🤸♀️",woman_cook:"👩🍳",woman_facepalming:"🤦♀️",woman_factory_worker:"👩🏭",woman_farmer:"👩🌾",woman_firefighter:"👩🚒",woman_health_worker:"👩⚕️",woman_judge:"👩⚖️",woman_juggling:"🤹♀️",woman_mechanic:"👩🔧",woman_office_worker:"👩💼",woman_pilot:"👩✈️",woman_playing_handball:"🤾♀️",woman_playing_water_polo:"🤽♀️",woman_scientist:"👩🔬",woman_shrugging:"🤷♀️",woman_singer:"👩🎤",woman_student:"👩🎓",woman_teacher:"👩🏫",woman_technologist:"👩💻",woman_with_turban:"👳♀️",womans_clothes:"👚",womans_hat:"👒",women_wrestling:"🤼♀️",womens:"🚺",world_map:"🗺",worried:"😟",wrench:"🔧",writing_hand:"✍️",x:"❌",yellow_heart:"💛",yen:"💴",yin_yang:"☯️",yum:"😋",zap:"⚡️",zipper_mouth_face:"🤐",zzz:"💤",octocat:'
',showdown:'
'},b.subParser("makehtml.blockGamut",function(e,r,t){"use strict";return e=t.converter._dispatch("makehtml.blockGamut.before",e,r,t).getText(),e=b.subParser("makehtml.blockQuotes")(e,r,t),e=b.subParser("makehtml.headers")(e,r,t),e=b.subParser("makehtml.horizontalRule")(e,r,t),e=b.subParser("makehtml.lists")(e,r,t),e=b.subParser("makehtml.codeBlocks")(e,r,t),e=b.subParser("makehtml.tables")(e,r,t),e=b.subParser("makehtml.hashHTMLBlocks")(e,r,t),e=b.subParser("makehtml.paragraphs")(e,r,t),e=t.converter._dispatch("makehtml.blockGamut.after",e,r,t).getText()}),b.subParser("makehtml.blockQuotes",function(e,r,t){"use strict";e=t.converter._dispatch("makehtml.blockQuotes.before",e,r,t).getText(),e+="\n\n";var a=/(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;return r.splitAdjacentBlockquotes&&(a=/^ {0,3}>[\s\S]*?(?:\n\n)/gm),e=e.replace(a,function(e){return e=(e=(e=e.replace(/^[ \t]*>[ \t]?/gm,"")).replace(/¨0/g,"")).replace(/^[ \t]+$/gm,""),e=b.subParser("makehtml.githubCodeBlocks")(e,r,t),e=(e=(e=b.subParser("makehtml.blockGamut")(e,r,t)).replace(/(^|\n)/g,"$1 ")).replace(/(\s*[^\r]+?<\/pre>)/gm,function(e,r){var t=r;return t=(t=t.replace(/^ /gm,"¨0")).replace(/¨0/g,"")}),b.subParser("makehtml.hashBlock")("\n"+e+"\n
",r,t)}),e=t.converter._dispatch("makehtml.blockQuotes.after",e,r,t).getText()}),b.subParser("makehtml.codeBlocks",function(e,o,i){"use strict";e=i.converter._dispatch("makehtml.codeBlocks.before",e,o,i).getText();return e=(e=(e+="¨0").replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g,function(e,r,t){var a=r,n=t,s="\n";return a=b.subParser("makehtml.outdent")(a,o,i),a=b.subParser("makehtml.encodeCode")(a,o,i),a=(a=(a=b.subParser("makehtml.detab")(a,o,i)).replace(/^\n+/g,"")).replace(/\n+$/g,""),o.omitExtraWLInCodeBlocks&&(s=""),a=""+a+s+"
",b.subParser("makehtml.hashBlock")(a,o,i)+n})).replace(/¨0/,""),e=i.converter._dispatch("makehtml.codeBlocks.after",e,o,i).getText()}),b.subParser("makehtml.codeSpans",function(e,s,o){"use strict";return void 0===(e=o.converter._dispatch("makehtml.codeSpans.before",e,s,o).getText())&&(e=""),e=e.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(e,r,t,a){var n=a;return n=(n=n.replace(/^([ \t]*)/g,"")).replace(/[ \t]*$/g,""),n=r+""+(n=b.subParser("makehtml.encodeCode")(n,s,o))+"",n=b.subParser("makehtml.hashHTMLSpans")(n,s,o)}),e=o.converter._dispatch("makehtml.codeSpans.after",e,s,o).getText()}),b.subParser("makehtml.completeHTMLDocument",function(e,r,t){"use strict";if(!r.completeHTMLDocument)return e;e=t.converter._dispatch("makehtml.completeHTMLDocument.before",e,r,t).getText();var a="html",n="\n",s="",o='\n',i="",l="";for(var c in void 0!==t.metadata.parsed.doctype&&(n="\n","html"!==(a=t.metadata.parsed.doctype.toString().toLowerCase())&&"html5"!==a||(o='')),t.metadata.parsed)if(t.metadata.parsed.hasOwnProperty(c))switch(c.toLowerCase()){case"doctype":break;case"title":s=""+t.metadata.parsed.title+"\n";break;case"charset":o="html"===a||"html5"===a?'\n':'\n';break;case"language":case"lang":i=' lang="'+t.metadata.parsed[c]+'"',l+='\n';break;default:l+='\n'}return e=n+"\n\n"+s+o+l+"\n\n"+e.trim()+"\n\n",e=t.converter._dispatch("makehtml.completeHTMLDocument.after",e,r,t).getText()}),b.subParser("makehtml.detab",function(e,r,t){"use strict";return e=(e=(e=(e=(e=(e=t.converter._dispatch("makehtml.detab.before",e,r,t).getText()).replace(/\t(?=\t)/g," ")).replace(/\t/g,"¨A¨B")).replace(/¨B(.+?)¨A/g,function(e,r){for(var t=r,a=4-t.length%4,n=0;n/g,">"),e=t.converter._dispatch("makehtml.encodeAmpsAndAngles.after",e,r,t).getText()}),b.subParser("makehtml.encodeBackslashEscapes",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("makehtml.encodeBackslashEscapes.before",e,r,t).getText()).replace(/\\(\\)/g,b.helper.escapeCharactersCallback)).replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g,b.helper.escapeCharactersCallback),e=t.converter._dispatch("makehtml.encodeBackslashEscapes.after",e,r,t).getText()}),b.subParser("makehtml.encodeCode",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.encodeCode.before",e,r,t).getText()).replace(/&/g,"&").replace(//g,">").replace(/([*_{}\[\]\\=~-])/g,b.helper.escapeCharactersCallback),e=t.converter._dispatch("makehtml.encodeCode.after",e,r,t).getText()}),b.subParser("makehtml.escapeSpecialCharsWithinTagAttributes",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("makehtml.escapeSpecialCharsWithinTagAttributes.before",e,r,t).getText()).replace(/<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,function(e){return e.replace(/(.)<\/?code>(?=.)/g,"$1`").replace(/([\\`*_~=|])/g,b.helper.escapeCharactersCallback)})).replace(/-]|-[^>])(?:[^-]|-[^-])*)--)>/gi,function(e){return e.replace(/([\\`*_~=|])/g,b.helper.escapeCharactersCallback)}),e=t.converter._dispatch("makehtml.escapeSpecialCharsWithinTagAttributes.after",e,r,t).getText()}),b.subParser("makehtml.githubCodeBlocks",function(e,s,o){"use strict";return s.ghCodeBlocks?(e=o.converter._dispatch("makehtml.githubCodeBlocks.before",e,s,o).getText(),e=(e=(e+="¨0").replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g,function(e,r,t,a){var n=s.omitExtraWLInCodeBlocks?"":"\n";return a=b.subParser("makehtml.encodeCode")(a,s,o),a=""+(a=(a=(a=b.subParser("makehtml.detab")(a,s,o)).replace(/^\n+/g,"")).replace(/\n+$/g,""))+n+"
",a=b.subParser("makehtml.hashBlock")(a,s,o),"\n\n¨G"+(o.ghCodeBlocks.push({text:e,codeblock:a})-1)+"G\n\n"})).replace(/¨0/,""),o.converter._dispatch("makehtml.githubCodeBlocks.after",e,s,o).getText()):e}),b.subParser("makehtml.hashBlock",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.hashBlock.before",e,r,t).getText()).replace(/(^\n+|\n+$)/g,""),e="\n\n¨K"+(t.gHtmlBlocks.push(e)-1)+"K\n\n",e=t.converter._dispatch("makehtml.hashBlock.after",e,r,t).getText()}),b.subParser("makehtml.hashCodeTags",function(e,s,o){"use strict";e=o.converter._dispatch("makehtml.hashCodeTags.before",e,s,o).getText();return e=b.helper.replaceRecursiveRegExp(e,function(e,r,t,a){var n=t+b.subParser("makehtml.encodeCode")(r,s,o)+a;return"¨C"+(o.gHtmlSpans.push(n)-1)+"C"},"]*>","","gim"),e=o.converter._dispatch("makehtml.hashCodeTags.after",e,s,o).getText()}),b.subParser("makehtml.hashElement",function(e,r,a){"use strict";return function(e,r){var t=r;return t=(t=(t=t.replace(/\n\n/g,"\n")).replace(/^\n/,"")).replace(/\n+$/g,""),t="\n\n¨K"+(a.gHtmlBlocks.push(t)-1)+"K\n\n"}}),b.subParser("makehtml.hashHTMLBlocks",function(e,r,s){"use strict";e=s.converter._dispatch("makehtml.hashHTMLBlocks.before",e,r,s).getText();var t=["pre","div","h1","h2","h3","h4","h5","h6","blockquote","table","dl","ol","ul","script","noscript","form","fieldset","iframe","math","style","section","header","footer","nav","article","aside","address","audio","canvas","figure","hgroup","output","video","p"],a=function(e,r,t,a){var n=e;return-1!==t.search(/\bmarkdown\b/)&&(n=t+s.converter.makeHtml(r)+a),"\n\n¨K"+(s.gHtmlBlocks.push(n)-1)+"K\n\n"};r.backslashEscapesHTMLTags&&(e=e.replace(/\\<(\/?[^>]+?)>/g,function(e,r){return"<"+r+">"}));for(var n=0;n]*>)","im"),l="<"+t[n]+"\\b[^>]*>",c=""+t[n]+">";-1!==(o=b.helper.regexIndexOf(e,i));){var u=b.helper.splitAtIndex(e,o),h=b.helper.replaceRecursiveRegExp(u[1],a,l,c,"im");if(h===u[1])break;e=u[0].concat(h)}return e=e.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,b.subParser("makehtml.hashElement")(e,r,s)),e=(e=b.helper.replaceRecursiveRegExp(e,function(e){return"\n\n¨K"+(s.gHtmlBlocks.push(e)-1)+"K\n\n"},"^ {0,3}\x3c!--","--\x3e","gm")).replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,b.subParser("makehtml.hashElement")(e,r,s)),e=s.converter._dispatch("makehtml.hashHTMLBlocks.after",e,r,s).getText()}),b.subParser("makehtml.hashHTMLSpans",function(e,r,t){"use strict";return e=(e=(e=(e=(e=t.converter._dispatch("makehtml.hashHTMLSpans.before",e,r,t).getText()).replace(/<[^>]+?\/>/gi,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<([^>]+?)>[\s\S]*?<\/\1>/g,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<[^>]+?>/gi,function(e){return b.helper._hashHTMLSpan(e,t)}),e=t.converter._dispatch("makehtml.hashHTMLSpans.after",e,r,t).getText()}),b.subParser("makehtml.unhashHTMLSpans",function(e,r,t){"use strict";e=t.converter._dispatch("makehtml.unhashHTMLSpans.before",e,r,t).getText();for(var a=0;a]*>\\s*]*>","^ {0,3}\\s*","gim"),e=o.converter._dispatch("makehtml.hashPreCodeTags.after",e,s,o).getText()}),b.subParser("makehtml.headers",function(e,l,c){"use strict";e=c.converter._dispatch("makehtml.headers.before",e,l,c).getText();var u=isNaN(parseInt(l.headerLevelStart))?1:parseInt(l.headerLevelStart),r=l.smoothLivePreview?/^(.+)[ \t]*\n={2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n=+[ \t]*\n+/gm,t=l.smoothLivePreview?/^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n-+[ \t]*\n+/gm;e=(e=e.replace(r,function(e,r){var t=b.subParser("makehtml.spanGamut")(r,l,c),a=l.noHeaderId?"":' id="'+h(r)+'"',n=""+t+"";return b.subParser("makehtml.hashBlock")(n,l,c)})).replace(t,function(e,r){var t=b.subParser("makehtml.spanGamut")(r,l,c),a=l.noHeaderId?"":' id="'+h(r)+'"',n=u+1,s=""+t+"";return b.subParser("makehtml.hashBlock")(s,l,c)});var a=l.requireSpaceBeforeHeadingText?/^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm:/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;function h(e){var r,t;if(l.customizedHeaderId){var a=e.match(/\{([^{]+?)}\s*$/);a&&a[1]&&(e=a[1])}return r=e,t=b.helper.isString(l.prefixHeaderId)?l.prefixHeaderId:!0===l.prefixHeaderId?"section-":"",l.rawPrefixHeaderId||(r=t+r),r=l.ghCompatibleHeaderId?r.replace(/ /g,"-").replace(/&/g,"").replace(/¨T/g,"").replace(/¨D/g,"").replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g,"").toLowerCase():l.rawHeaderId?r.replace(/ /g,"-").replace(/&/g,"&").replace(/¨T/g,"¨").replace(/¨D/g,"$").replace(/["']/g,"-").toLowerCase():r.replace(/[^\w]/g,"").toLowerCase(),l.rawPrefixHeaderId&&(r=t+r),c.hashLinkCounts[r]?r=r+"-"+c.hashLinkCounts[r]++:c.hashLinkCounts[r]=1,r}return e=e.replace(a,function(e,r,t){var a=t;l.customizedHeaderId&&(a=t.replace(/\s?\{([^{]+?)}\s*$/,""));var n=b.subParser("makehtml.spanGamut")(a,l,c),s=l.noHeaderId?"":' id="'+h(t)+'"',o=u-1+r.length,i=""+n+"";return b.subParser("makehtml.hashBlock")(i,l,c)}),e=c.converter._dispatch("makehtml.headers.after",e,l,c).getText()}),b.subParser("makehtml.horizontalRule",function(e,r,t){"use strict";e=t.converter._dispatch("makehtml.horizontalRule.before",e,r,t).getText();var a=b.subParser("makehtml.hashBlock")("
",r,t);return e=(e=(e=e.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?_){3,}[ \t]*$/gm,a),e=t.converter._dispatch("makehtml.horizontalRule.after",e,r,t).getText()}),b.subParser("makehtml.images",function(e,r,m){"use strict";function l(e,r,t,a,n,s,o,i){var l=m.gUrls,c=m.gTitles,u=m.gDimensions;if(t=t.toLowerCase(),i||(i=""),-1? ?(['"].*['"])?\)$/m))a="";else if(""===a||null===a){if(""!==t&&null!==t||(t=r.toLowerCase().replace(/ ?\n/g," ")),a="#"+t,b.helper.isUndefined(l[t]))return e;a=l[t],b.helper.isUndefined(c[t])||(i=c[t]),b.helper.isUndefined(u[t])||(n=u[t].width,s=u[t].height)}r=r.replace(/"/g,""").replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback);var h='
"}return e=(e=(e=(e=(e=(e=m.converter._dispatch("makehtml.images.before",e,r,m).getText()).replace(/!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,l)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,function(e,r,t,a,n,s,o,i){return l(e,r,t,a=a.replace(/\s/g,""),n,s,0,i)})).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,l)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,l)).replace(/!\[([^\[\]]+)]()()()()()/g,l),e=m.converter._dispatch("makehtml.images.after",e,r,m).getText()}),b.subParser("makehtml.italicsAndBold",function(e,r,t){"use strict";function a(e,r,t){return r+e+t}return e=t.converter._dispatch("makehtml.italicsAndBold.before",e,r,t).getText(),e=(e=(e=(e=r.literalMidWordUnderscores?(e=(e=e.replace(/\b___(\S[\s\S]*)___\b/g,function(e,r){return a(r,"","")})).replace(/\b__(\S[\s\S]*)__\b/g,function(e,r){return a(r,"","")})).replace(/\b_(\S[\s\S]*?)_\b/g,function(e,r){return a(r,"","")}):(e=(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,r){return/\S$/.test(r)?a(r,"",""):e})).replace(/__(\S[\s\S]*?)__/g,function(e,r){return/\S$/.test(r)?a(r,"",""):e})).replace(/_([^\s_][\s\S]*?)_/g,function(e,r){return/\S$/.test(r)?a(r,"",""):e})).replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g,function(e,r){return/\S$/.test(r)?a(r,"",""):e})).replace(/\*\*(\S[\s\S]*?)\*\*/g,function(e,r){return/\S$/.test(r)?a(r,"",""):e})).replace(/\*([^\s*][\s\S]*?)\*/g,function(e,r){return/\S$/.test(r)?a(r,"",""):e}),e=t.converter._dispatch("makehtml.italicsAndBold.after",e,r,t).getText()}),function(){function l(i,l,c,u,h){return h=!!h,function(e,r,t,a,n,s,o){return/\n\n/.test(e)?e:f(_(i,l+".captureStart",e,r,t,a,o,c,u),c,u,h)}}function _(e,r,t,a,n,s,o,i,l){return l.converter._dispatch(r,t,i,l,{regexp:e,matches:{wholeMatch:t,text:a,id:n,url:s,title:o}})}function f(e,r,t,a){var n=e.getMatches().wholeMatch,s=e.getMatches().text,o=e.getMatches().id,i=e.getMatches().url,l=e.getMatches().title,c="";if(l||(l=""),o=o?o.toLowerCase():"",a)i="";else if(!i){if(o||(o=s.toLowerCase().replace(/ ?\n/g," ")),i="#"+o,b.helper.isUndefined(t.gUrls[o]))return n;i=t.gUrls[o],b.helper.isUndefined(t.gTitles[o])||(l=t.gTitles[o])}i=i.replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback),""!==l&&null!==l&&(l=' title="'+(l=(l=l.replace(/"/g,""")).replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback))+'"'),r.openLinksInNewWindow&&!/^#/.test(i)&&(c=' target="¨E95Eblank"'),s=b.subParser("makehtml.codeSpans")(s,r,t),s=b.subParser("makehtml.emoji")(s,r,t),s=b.subParser("makehtml.underline")(s,r,t),s=b.subParser("makehtml.italicsAndBold")(s,r,t),s=b.subParser("makehtml.strikethrough")(s,r,t),s=b.subParser("makehtml.ellipsis")(s,r,t);var u='"+(s=b.subParser("makehtml.hashHTMLSpans")(s,r,t))+"";return u=b.subParser("makehtml.hashHTMLSpans")(u,r,t)}var a="makehtml.links";b.subParser("makehtml.links",function(e,r,t){return e=t.converter._dispatch(a+".start",e,r,t).getText(),e=b.subParser("makehtml.links.reference")(e,r,t),e=b.subParser("makehtml.links.inline")(e,r,t),e=b.subParser("makehtml.links.referenceShortcut")(e,r,t),e=b.subParser("makehtml.links.angleBrackets")(e,r,t),e=(e=(e=b.subParser("makehtml.links.ghMentions")(e,r,t)).replace(/]*>[\s\S]*<\/a>/g,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/
]*\/?>/g,function(e){return b.helper._hashHTMLSpan(e,t)}),e=b.subParser("makehtml.links.naked")(e,r,t),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.inline",function(e,r,t){var a=a+".inline",n=/\[(.*?)]()()()()\( ?>? ?(?:["'](.*)["'])?\)/g,s=/\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,o=/\[([\S ]*?)]\s?()\( *([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s*(?:()(['"])(.*?)\5)? *\)/g,i=/\[([\S ]*?)]\s?()\( *([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s+()()\((.*?)\) *\)/g;return e=(e=(e=(e=(e=t.converter._dispatch(a+".start",e,r,t).getText()).replace(n,l(n,a,r,t,!0))).replace(s,l(s,a,r,t))).replace(o,l(o,a,r,t))).replace(i,l(i,a,r,t)),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.reference",function(e,r,t){var a=a+".reference",n=/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;return e=(e=t.converter._dispatch(a+".start",e,r,t).getText()).replace(n,l(n,a,r,t)),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.referenceShortcut",function(e,r,t){var a=a+".referenceShortcut",n=/\[([^\[\]]+)]()()()()()/g;return e=(e=t.converter._dispatch(a+".start",e,r,t).getText()).replace(n,l(n,a,r,t)),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.ghMentions",function(e,o,i){var l=l+"ghMentions";if(!o.ghMentions)return e;e=i.converter._dispatch(l+".start",e,o,i).getText();var c=/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi;return e=e.replace(c,function(e,r,t,a,n){if("\\"===t)return r+a;if(!b.helper.isString(o.ghMentionsLink))throw new Error("ghMentionsLink option must be a string");var s=o.ghMentionsLink.replace(/{u}/g,n);return r+f(_(c,l+".captureStart",e,a,null,s,null,o,i),o,i)}),e=i.converter._dispatch(l+".end",e,o,i).getText()}),b.subParser("makehtml.links.angleBrackets",function(e,a,n){var s="makehtml.links.angleBrackets";e=n.converter._dispatch(s+".start",e,a,n).getText();var o=/<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi;e=e.replace(o,function(e,r,t){return f(_(o,s+".captureStart",e,r,null,r="www."===t?"http://"+r:r,null,a,n),a,n)});var i=/<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;return e=e.replace(i,function(e,r){var t="mailto:";return r=b.subParser("makehtml.unescapeSpecialChars")(r,a,n),a.encodeEmails?(t=b.helper.encodeEmailAddress(t+r),r=b.helper.encodeEmailAddress(r)):t+=r,f(_(i,s+".captureStart",e,r,null,t,null,a,n),a,n)}),e=n.converter._dispatch(s+".end",e,a,n).getText()}),b.subParser("makehtml.links.naked",function(e,m,d){if(!m.simplifiedAutoLink)return e;var p="makehtml.links.naked";e=d.converter._dispatch(p+".start",e,m,d).getText();var g=/([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi;e=e.replace(g,function(e,r,t,a){for(var n="",s=t.length-1;0<=s;--s){var o=t.charAt(s);if(/[_*~,;:.!?]/.test(o))t=t.slice(0,-1),n=o+n;else if(/\)/.test(o)){var i=t.match(/\(/g)||[],l=t.match(/\)/g);if(!(i.length"})),i=i.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g,function(e){return"¨A"+e}),/^#+.+\n.+/.test(i)&&(i=i.replace(/^(#+.+)$/m,"$1\n")),r||-1"+(i=i.replace("¨A",""))+"\n"})).replace(/¨0/g,""),u.gListLevel--,r&&(e=e.replace(/\s+$/,"")),e}function d(e,r){if("ol"===r){var t=e.match(/^ *(\d+)\./);if(t&&"1"!==t[1])return' start="'+t[1]+'"'}return""}function n(n,s,o){var i=h.disableForced4SpacesIndentedSublists?/^ ?\d+\.[ \t]/gm:/^ {0,3}\d+\.[ \t]/gm,l=h.disableForced4SpacesIndentedSublists?/^ ?[*+-][ \t]/gm:/^ {0,3}[*+-][ \t]/gm,c="ul"===s?i:l,u="";if(-1!==n.search(c))!function e(r){var t=r.search(c),a=d(n,s);-1!==t?(u+="\n\n<"+s+a+">\n"+m(r.slice(0,t),!!o)+""+s+">\n",c="ul"===(s="ul"===s?"ol":"ul")?i:l,e(r.slice(t))):u+="\n\n<"+s+a+">\n"+m(r,!!o)+""+s+">\n"}(n);else{var e=d(n,s);u="\n\n<"+s+e+">\n"+m(n,!!o)+""+s+">\n"}return u}return e=u.converter._dispatch("lists.before",e,h,u).getText(),e+="¨0",e=(e=u.gListLevel?e.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,r,t){return n(r,-1"),i+="
",n.push(i))}for(s=n.length,o=0;o]*>\s*]*>/.test(c)&&(u=!0)}n[o]=c}return e=(e=(e=n.join("\n")).replace(/^\n+/g,"")).replace(/\n+$/g,""),t.converter._dispatch("makehtml.paragraphs.after",e,r,t).getText()}),b.subParser("makehtml.runExtension",function(e,r,t,a){"use strict";if(e.filter)r=e.filter(r,a.converter,t);else if(e.regex){var n=e.regex;n instanceof RegExp||(n=new RegExp(n,"g")),r=r.replace(n,e.replace)}return r}),b.subParser("makehtml.spanGamut",function(e,r,t){"use strict";return e=t.converter._dispatch("makehtml.span.before",e,r,t).getText(),e=b.subParser("makehtml.codeSpans")(e,r,t),e=b.subParser("makehtml.escapeSpecialCharsWithinTagAttributes")(e,r,t),e=b.subParser("makehtml.encodeBackslashEscapes")(e,r,t),e=b.subParser("makehtml.images")(e,r,t),e=t.converter._dispatch("smakehtml.links.before",e,r,t).getText(),e=b.subParser("makehtml.links")(e,r,t),e=t.converter._dispatch("smakehtml.links.after",e,r,t).getText(),e=b.subParser("makehtml.emoji")(e,r,t),e=b.subParser("makehtml.underline")(e,r,t),e=b.subParser("makehtml.italicsAndBold")(e,r,t),e=b.subParser("makehtml.strikethrough")(e,r,t),e=b.subParser("makehtml.ellipsis")(e,r,t),e=b.subParser("makehtml.hashHTMLSpans")(e,r,t),e=b.subParser("makehtml.encodeAmpsAndAngles")(e,r,t),r.simpleLineBreaks?/\n\n¨K/.test(e)||(e=e.replace(/\n+/g,"
\n")):e=e.replace(/ +\n/g,"
\n"),e=t.converter._dispatch("makehtml.spanGamut.after",e,r,t).getText()}),b.subParser("makehtml.strikethrough",function(e,r,t){"use strict";return r.strikethrough&&(e=(e=t.converter._dispatch("makehtml.strikethrough.before",e,r,t).getText()).replace(/(?:~){2}([\s\S]+?)(?:~){2}/g,function(e,r){return""+r+""}),e=t.converter._dispatch("makehtml.strikethrough.after",e,r,t).getText()),e}),b.subParser("makehtml.stripLinkDefinitions",function(e,i,l){"use strict";var r=function(e,r,t,a,n,s,o){return r=r.toLowerCase(),t.match(/^data:.+?\/.+?;base64,/)?l.gUrls[r]=t.replace(/\s/g,""):l.gUrls[r]=b.subParser("makehtml.encodeAmpsAndAngles")(t,i,l),s?s+o:(o&&(l.gTitles[r]=o.replace(/"|'/g,""")),i.parseImgDimensions&&a&&n&&(l.gDimensions[r]={width:a,height:n}),"")};return e=(e=(e=(e+="¨0").replace(/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm,r)).replace(/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,r)).replace(/¨0/,"")}),b.subParser("makehtml.tables",function(e,_,f){"use strict";if(!_.tables)return e;function r(e){var r,t=e.split("\n");for(r=0;r"+(n=b.subParser("makehtml.spanGamut")(n,_,f))+"\n"));for(r=0;r"+b.subParser("makehtml.spanGamut")(i,_,f)+"\n"));d.push(p)}return function(e,r){for(var t="\n"}(h,d)}return e=(e=(e=(e=f.converter._dispatch("makehtml.tables.before",e,_,f).getText()).replace(/\\(\|)/g,b.helper.escapeCharactersCallback)).replace(/^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,r)).replace(/^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm,r),e=f.converter._dispatch("makehtml.tables.after",e,_,f).getText()}),b.subParser("makehtml.underline",function(e,r,t){"use strict";return r.underline?(e=t.converter._dispatch("makehtml.underline.before",e,r,t).getText(),e=(e=r.literalMidWordUnderscores?e.replace(/\b_?__(\S[\s\S]*)___?\b/g,function(e,r){return""+r+""}):e.replace(/_?__(\S[\s\S]*?)___?/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/(_)/g,b.helper.escapeCharactersCallback),e=t.converter._dispatch("makehtml.underline.after",e,r,t).getText()):e}),b.subParser("makehtml.unescapeSpecialChars",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.unescapeSpecialChars.before",e,r,t).getText()).replace(/¨E(\d+)E/g,function(e,r){var t=parseInt(r);return String.fromCharCode(t)}),e=t.converter._dispatch("makehtml.unescapeSpecialChars.after",e,r,t).getText()}),b.subParser("makeMarkdown.blockquote",function(e,r){"use strict";var t="";if(e.hasChildNodes())for(var a=e.childNodes,n=a.length,s=0;s ")}),b.subParser("makeMarkdown.codeBlock",function(e,r){"use strict";var t=e.getAttribute("language"),a=e.getAttribute("precodenum");return"```"+t+"\n"+r.preList[a]+"\n```"}),b.subParser("makeMarkdown.codeSpan",function(e){"use strict";return"`"+e.innerHTML+"`"}),b.subParser("makeMarkdown.emphasis",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="*";for(var a=e.childNodes,n=a.length,s=0;s",e.hasAttribute("width")&&e.hasAttribute("height")&&(r+=" ="+e.getAttribute("width")+"x"+e.getAttribute("height")),e.hasAttribute("title")&&(r+=' "'+e.getAttribute("title")+'"'),r+=")"),r}),b.subParser("makeMarkdown.links",function(e,r){"use strict";var t="";if(e.hasChildNodes()&&e.hasAttribute("href")){var a=e.childNodes,n=a.length;t="[";for(var s=0;s",e.hasAttribute("title")&&(t+=' "'+e.getAttribute("title")+'"'),t+=")"}return t}),b.subParser("makeMarkdown.list",function(e,r,t){"use strict";var a="";if(!e.hasChildNodes())return"";for(var n=e.childNodes,s=n.length,o=e.getAttribute("start")||1,i=0;i"+r.preList[t]+""}),b.subParser("makeMarkdown.strikethrough",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="~~";for(var a=e.childNodes,n=a.length,s=0;str>th"),i=e.querySelectorAll("tbody>tr");for(t=0;t/g,"\\$1>")).replace(/^#/gm,"\\#")).replace(/^(\s*)([-=]{3,})(\s*)$/,"$1\\$2$3")).replace(/^( {0,3}\d+)\./gm,"$1\\.")).replace(/^( {0,3})([+-])/gm,"$1\\$2")).replace(/]([\s]*)\(/g,"\\]$1\\(")).replace(/^ {0,3}\[([\S \t]*?)]:/gm,"\\[$1]:")}),b.Converter=function(t){"use strict";var s={},o=[],i=[],c={},a=d,l={parsed:{},raw:"",format:""};function n(e,r){if(r=r||null,b.helper.isString(e)){if(r=e=b.helper.stdExtName(e),b.extensions[e])return console.warn("DEPRECATION WARNING: "+e+" is an old extension that uses a deprecated loading method.Please inform the developer that the extension should be updated!"),void function(e,r){"function"==typeof e&&(e=e(new b.Converter));b.helper.isArray(e)||(e=[e]);var t=g(e,r);if(!t.valid)throw Error(t.error);for(var a=0;a[ \t]+,">¨NBSP;<");var r=b.helper.document.createElement("div");r.innerHTML=e;var t={preList:function(e){for(var r=e.querySelectorAll("pre"),t=[],a=0;a'}else t.push(r[a].innerHTML),r[a].innerHTML="",r[a].setAttribute("prenum",a.toString());return t}(r)};!function e(r){for(var t=0;t 0
+ $oP->add('');
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // Newsroom
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ $iCountProviders = 0;
+ $oUser = UserRights::GetUserObject();
+ $aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
+ foreach($aProviders as $oProvider)
+ {
+ if ($oProvider->IsApplicable($oUser))
+ {
+ $iCountProviders++;
+ }
+ }
+
+ $bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false);
+ if ($bNewsroomEnabled && ($iCountProviders > 0))
+ {
+ $oP->add('');
+ }
+
//////////////////////////////////////////////////////////////////////////
//
// Footer
@@ -365,6 +438,53 @@ try
DisplayPreferences($oPage);
break;
+ case 'apply_newsroom_preferences':
+ $iCountProviders = 0;
+ $oUser = UserRights::GetUserObject();
+ $aProviders = MetaModel::EnumPlugins('iNewsroomProvider');
+ foreach($aProviders as $oProvider)
+ {
+ if ($oProvider->IsApplicable($oUser))
+ {
+ $iCountProviders++;
+ }
+ }
+ $bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false);
+ if ($bNewsroomEnabled && ($iCountProviders > 0))
+ {
+ $iNewsroomDisplaySize = (int)utils::ReadParam('newsroom_display_size', 7);
+ if ($iNewsroomDisplaySize < 1) $iNewsroomDisplaySize = 1;
+ if ($iNewsroomDisplaySize > 20) $iNewsroomDisplaySize = 20;
+ $iCurrentDisplaySize = (int)appUserPreferences::GetPref('newsroom_display_size', $iNewsroomDisplaySize);
+ if ($iCurrentDisplaySize != $iNewsroomDisplaySize)
+ {
+ // Save the preference only if it differs from the current (or default) value
+ appUserPreferences::SetPref('newsroom_display_size', $iNewsroomDisplaySize);
+ }
+ }
+ $bProvidersModified = false;
+ foreach($aProviders as $oProvider)
+ {
+ if ($oProvider->IsApplicable($oUser))
+ {
+ $sProviderClass = get_class($oProvider);
+ $bProviderEnabled = (utils::ReadParam('newsroom_provider_'.$sProviderClass, 'off') == 'on');
+ $bCurrentValue = appUserPreferences::GetPref('newsroom_provider_'.$sProviderClass, true);
+ if ($bCurrentValue != $bProviderEnabled)
+ {
+ // Save the preference only if it differs from the current value
+ $bProvidersModified = true;
+ appUserPreferences::SetPref('newsroom_provider_'.$sProviderClass, $bProviderEnabled);
+ }
+ }
+ }
+ if ($bProvidersModified)
+ {
+ $oPage->add_ready_script('$(".itop-newsroom_menu").newsroom_menu("clearCache");');
+ }
+ DisplayPreferences($oPage);
+ break;
+
case 'display':
default:
$oPage->SetBreadCrumbEntry('ui-tool-preferences', Dict::S('UI:Preferences'), Dict::S('UI:Preferences'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');