This commit is contained in:
Ty Clifford
2026-07-03 07:31:09 -04:00
commit cebb0d3af1
800 changed files with 89782 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "За мен",
"description": "Кратко описание за вашия сайт или за себе си."
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"plugin-data": {
"description": "Vis en lille beskrivelse af dit websted eller om dig selv.",
"name": "About"
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Über",
"description": "Kurzer Text über die Website oder zum Betreiber des Blogs oder der Website."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Über",
"description": "Kurzer Text über die Website oder zum Betreiber des Blogs oder der Website."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "About",
"description": "Show a small description of your site or about yourself."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Acerca de",
"description": "Breve descripción de ti mismo o sobre tu sitio."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "درباره",
"description": "نمایش توضیح کوتاهی از شما و یا وبسایتتان."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "À Propos",
"description": "Afficher une courte description sur votre site ou sur vous-même."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Informazioni",
"description": "Visualizza una breve descrizione sul tuo sito o su te stesso."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "About",
"description": "サイトやあなたについての簡単な説明を表示します。"
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Over",
"description": "Een korte beschrijving over de site of over uzelf."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "О блоге",
"description": "Небольшое описание о вашем сайте или о себе."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Hakkında",
"description": "Senin veya siten hakkında kısa bilgiler"
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Про блог",
"description": "Невеликий опис вашого сайту або про Вас."
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": ""
}
+47
View File
@@ -0,0 +1,47 @@
<?php
class pluginAbout extends Plugin
{
public function init()
{
$this->dbFields = array(
'label' => 'About',
'text' => ''
);
}
public function form()
{
global $L;
$html = '<div class="alert alert-primary" role="alert">';
$html .= $this->description();
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('Label') . '</label>';
$html .= '<input name="label" type="text" dir="auto" value="' . $this->getValue('label') . '">';
$html .= '<span class="tip">' . $L->get('This title is almost always used in the sidebar of the site') . '</span>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('About') . '</label>';
$html .= '<textarea name="text" id="jstext">' . $this->getValue('text') . '</textarea>';
$html .= '</div>';
return $html;
}
public function siteSidebar()
{
$html = '<div class="plugin plugin-about">';
$html .= '<h2 class="plugin-label">' . $this->getValue('label') . '</h2>';
$html .= '<div class="plugin-content">';
$html .= html_entity_decode(nl2br($this->getValue('text')));
$html .= '</div>';
$html .= '</div>';
return $html;
}
}
@@ -0,0 +1,14 @@
{
"plugin-data":
{
"name": "Theme Popeye",
"description": "Das Plugin erlaubt verschiedene Einstellungen für das Theme Popeye."
},
"enable-or-disable-dark-mode": "Dunkelmodus aktivieren oder deaktivieren.",
"enable-or-disable-google-fonts": "Google Fonts aktivieren oder deaktivieren.",
"relative": "Relativ",
"absolute": "Absolut",
"change-the-date-format-for-the-main-page": "Einstellung des Datumsformats auf der Haupt- oder Blogseite.",
"show-tags": "Schlagwörter zeigen",
"show-tags-in-the-main-page-for-each-article": "Zeigt auf der Haupt- oder Blogseite die Schlagwörter der Beiträge."
}
@@ -0,0 +1,14 @@
{
"plugin-data":
{
"name": "Theme Popeye",
"description": "Das Plugin erlaubt verschiedene Einstellungen für das Theme Popeye."
},
"enable-or-disable-dark-mode": "Dunkelmodus aktivieren oder deaktivieren.",
"enable-or-disable-google-fonts": "Google Fonts aktivieren oder deaktivieren.",
"relative": "Relativ",
"absolute": "Absolut",
"change-the-date-format-for-the-main-page": "Einstellung des Datumsformats auf der Haupt- oder Blogseite.",
"show-tags": "Schlagwörter zeigen",
"show-tags-in-the-main-page-for-each-article": "Zeigt auf der Haupt- oder Blogseite die Schlagwörter der Beiträge."
}
@@ -0,0 +1,14 @@
{
"plugin-data":
{
"name": "Theme Popeye",
"description": "Das Plugin erlaubt verschiedene Einstellungen für das Theme Popeye."
},
"enable-or-disable-dark-mode": "Dunkelmodus aktivieren oder deaktivieren.",
"enable-or-disable-google-fonts": "Google Fonts aktivieren oder deaktivieren.",
"relative": "Relativ",
"absolute": "Absolut",
"change-the-date-format-for-the-main-page": "Einstellung des Datumsformats auf der Haupt- oder Blogseite.",
"show-tags": "Schlagwörter zeigen",
"show-tags-in-the-main-page-for-each-article": "Zeigt auf der Haupt- oder Blogseite die Schlagwörter der Beiträge."
}
+13
View File
@@ -0,0 +1,13 @@
{
"plugin-data": {
"name": "Alternative Theme",
"description": "This plugin provides configuration for the Alternative theme."
},
"enable-or-disable-dark-mode": "Enable or disable dark mode.",
"enable-or-disable-google-fonts": "Enable or disable Google fonts.",
"relative": "Relative",
"absolute": "Absolute",
"change-the-date-format-for-the-main-page": "Change the date format for the main page.",
"show-tags": "Show tags",
"show-tags-in-the-main-page-for-each-article": "Show tags on the main page for each article."
}
@@ -0,0 +1,14 @@
{
"plugin-data":
{
"name": "Popeye Theme",
"description": "Popeyeテーマの設定を行うプラグインです。"
},
"enable-or-disable-dark-mode": "ダークモードを有効または無効にします。",
"enable-or-disable-google-fonts": "Google Fontsの利用を有効または無効にします。",
"relative": "相対的",
"absolute": "絶対的",
"change-the-date-format-for-the-main-page": "メインページの日付表示形式を変更します。",
"show-tags": "タグの表示",
"show-tags-in-the-main-page-for-each-article": "メインページの各記事にタグを表示します。"
}
@@ -0,0 +1,14 @@
{
"plugin-data":
{
"name": "Popeye Thema",
"description": "Met deze plugin kan het thema Popeye geconfigureerd worden."
},
"enable-or-disable-dark-mode": "Donkere modus in-/uitschakelen.",
"enable-or-disable-google-fonts": "Lettertypes van Google in-/uitschakelen.",
"relative": "Relatief",
"absolute": "Absoluut",
"change-the-date-format-for-the-main-page": "Het datumformaat voor de hoofdpagina aanpassen.",
"show-tags": "Tags tonen",
"show-tags-in-the-main-page-for-each-article": "Op de hoofdpagina voor ieder artikel de tags tonen."
}
+13
View File
@@ -0,0 +1,13 @@
{
"plugin-data": {
"name": "Настройки темы Alternative",
"description": "Этот плагин содержит настройки для темы Alternative."
},
"enable-or-disable-dark-mode": "Включить или выключить тёмный режим.",
"enable-or-disable-google-fonts": "Включить или выключить шрифты от Google (Google fonts).",
"relative": "Относительный",
"absolute": "Абсолютный",
"change-the-date-format-for-the-main-page": "Изменить формат даты для главной страницы.",
"show-tags": "Отображать теги",
"show-tags-in-the-main-page-for-each-article": "Показывать теги на главной странице для каждой записи."
}
+11
View File
@@ -0,0 +1,11 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": "",
"type": "theme"
}
+65
View File
@@ -0,0 +1,65 @@
<?php
class alternative extends Plugin
{
public function init()
{
$this->dbFields = array(
'googleFonts' => false,
'showPostInformation' => false,
'dateFormat' => 'relative'
);
}
public function form()
{
global $L;
$html = '';
$html .= '<div class="mb-3">';
$html .= '<label class="form-label" for="googleFonts">' . $L->get('Google Fonts') . '</label>';
$html .= '<select class="form-select" id="googleFonts" name="googleFonts">';
$html .= '<option value="false" ' . ($this->getValue('googleFonts') === false ? 'selected' : '') . '>' . $L->get('Disabled') . '</option>';
$html .= '<option value="true" ' . ($this->getValue('googleFonts') === true ? 'selected' : '') . '>' . $L->get('Enabled') . '</option>';
$html .= '</select>';
$html .= '<div class="form-text">' . $L->get('Enable or disable Google fonts.') . '</div>';
$html .= '</div>';
$html .= '<div class="mb-3">';
$html .= '<label class="form-label" for="showPostInformation">' . $L->get('Show Post Information') . '</label>';
$html .= '<select class="form-select" id="showPostInformation" name="showPostInformation">';
$html .= '<option value="false" ' . ($this->getValue('showPostInformation') === false ? 'selected' : '') . '>' . $L->get('Disabled') . '</option>';
$html .= '<option value="true" ' . ($this->getValue('showPostInformation') === true ? 'selected' : '') . '>' . $L->get('Enabled') . '</option>';
$html .= '</select>';
$html .= '</div>';
$html .= '<div class="mb-3">';
$html .= '<label class="form-label" for="dateFormat">' . $L->get('Date format') . '</label>';
$html .= '<select class="form-select" id="dateFormat" name="dateFormat">';
$html .= '<option value="noshow" ' . ($this->getValue('dateFormat') == 'noshow' ? 'selected' : '') . '>' . $L->get('No show') . '</option>';
$html .= '<option value="relative" ' . ($this->getValue('dateFormat') == 'relative' ? 'selected' : '') . '>' . $L->get('Relative') . '</option>';
$html .= '<option value="absolute" ' . ($this->getValue('dateFormat') == 'absolute' ? 'selected' : '') . '>' . $L->get('Absolute') . '</option>';
$html .= '</select>';
$html .= '<div class="form-text">' . $L->get('Change the date format for the main page.') . '</div>';
$html .= '</div>';
return $html;
}
public function showPostInformation()
{
return $this->getValue('showPostInformation');
}
public function googleFonts()
{
return $this->getValue('googleFonts');
}
public function dateFormat()
{
return $this->getValue('dateFormat');
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"amount-of-pages": "Antal af sider",
"api-token": "API-token",
"plugin-data": {
"description": "Grænseflade til interaktion med Bludit ved hjælp af HTTP-protokol. <br> Læs mere om denne udvidelse i <a href=\"https://docs.bludit.com/en/api/introduction\">API-introduktion</a>.",
"name": "API"
},
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Dette er det maksimale antal sider, der skal returneres, når du lavet et kald til / api / sider",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Denne token er kun læsbar og regenereres hver gang du installerer udvidelsen."
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Schnittstelle, für den Datenaustausch mit Bludit über das HTTP-Protokoll. Informationen zur Verwendung des Plugins unter <a href=\"https://docs.bludit.com/en/api/introduction\">API Introduction</a>."
},
"api-token": "API-Token",
"amount-of-pages": "Anzahl Seiten",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Maximum der Seiten bei einem Aufruf /api/pages.",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Der Token kann für Leserechte verwendet werden. Er wird bei bei einer Neuinstallation des Plugins erneuert."
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Schnittstelle, für den Datenaustausch mit Bludit über das HTTP-Protokoll. Informationen zur Verwendung des Plugins unter <a href=\"https://docs.bludit.com/en/api/introduction\">API Introduction</a>."
},
"api-token": "API-Token",
"amount-of-pages": "Anzahl Seiten",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Maximum der Seiten bei einem Aufruf /api/pages.",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Der Token kann für Leserechte verwendet werden. Er wird bei bei einer Neuinstallation des Plugins erneuert."
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Interface to interact with Bludit using HTTP protocol. <br> Read more about this plugin on <a href=\"https://docs.bludit.com/en/api/introduction\">API Introduction</a>."
},
"api-token": "API Token",
"amount-of-pages": "Amount of pages",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "This is the maximum of pages to return when you call to /api/pages",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "This token is for read only and is regenerated every time you install the plugin"
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Interfaz para interactuar con Bludit mediante el protocolo HTTP. <br>Leer más sobre este plugin en <a href=\"https://docs.bludit.com/en/api/introduction\">API introducción</a>."
},
"api-token": "API Token",
"amount-of-pages": "Cantidad de paginas",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Este es el máximo de páginas a devolver cuando llame a /api/pages.",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Este token es para sólo lectura y se regenera cada vez que se instala el plugin."
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "رابطی برای ارتباط با بلودیت با استفاده از پروتکل HTTP.<br>اطلاعات بیشتر را درمورد این پلاگین از <a href=\"https://docs.bludit.com/en/api/introduction\">API Introduction</a> مطالعه کنید."
},
"api-token": "رمز توکن API",
"amount-of-pages": "تعداد صفحات",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "این حداکثر صفحاتی بازگشتی است هنگامی که /api/pages را بازخوانی می‌کنید",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "این توکن تنها خواندی است و هر زمانی که پلاگین را نصب می کنید بازسازی می شود"
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Interface pour interagir avec Bludit en utilisant le protocole HTTP. <br>En savoir plus sur ce plugin, en lisant <a href=\"https://docs.bludit.com/en/api/introduction\">lintroduction sur lAPI</a>."
},
"api-token": "Jeton de lAPI",
"amount-of-pages": "Nombre de pages",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Cest le nombre maximal de pages à renvoyer lorsque vous appelez lapi par pages.",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Ce jeton est en lecture seule et est régénéré à chaque fois que vous installez le plugin."
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Interfaccia per interagire con Bludit utilizzando il protocollo HTTP. <br> Leggi di più su questo plugin su <a href=\"https://docs.bludit.com/en/api/introduction\">API Introduction</a>."
},
"api-token": "Token API",
"amount-of-pages": "Quantità di pagine",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Questo è il numero di pagine di ritorno quando effetui una chiamata /api/pages",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Questo token è di sola lettura e viene rigenerato ogni volta che installi il plugin"
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "HTTPを使用してBluditとやり取りするインターフェース。<br> このプラグインについては <a href=\"https:\/\/docs.bludit.com\/en\/api\/introduction\">API Introduction<\/a> を参照してください。"
},
"api-token": "APIトークン",
"amount-of-pages": "ページ数",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "これは \/api\/pages 呼び出し時に返される最大ページ数です",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "このトークンは読み取り専用トークンで、プラグインをインストールするたびに再生成されます"
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Interface om met Bludit te communiceren via het HTTP-protocol. <br>Lees meer over deze plugin op <a href=\"https://docs.bludit.com/en/api/introduction\">API Introduction</a>."
},
"api-token": "API-token",
"amount-of-pages": "Aantal pagina's",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Het maximum aantal door te sturen pagina's via een call naar /api/pages",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Dit token is niet aan te passen en wordt automatisch ververst wanneer de plugin opnieuw wordt ge&iuml;nstalleerd"
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "Интерфейс для взаимодействия с Bludit по HTTP-протоколу.<br>Узнайте больше про этот плагин в разделе <a href=\"https://docs.bludit.com/en/api/introduction\">Введение в API для Bludit</a> (раздел на английском)."
},
"api-token": "API Tокен",
"amount-of-pages": "Количество страниц",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Максимальное количество возвращаемых страниц при обращении к <code>/api/pages</code>",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Данный токен используется только для чтения, токен обновляется при каждой переустановке плагина."
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data":
{
"name": "API",
"description": "HTTP protokolünü kullanarak Bludit ile etkileşimde bulunmak için arabirim. <br> Bu eklenti hakkında daha fazla bilgi için <a href=\"https://docs.bludit.com/en/api/introduction\">API Tanıtımı (ingilizce)</a>."
},
"api-token": "API Token",
"amount-of-pages": "Sayfa miktarı",
"this-is-the-maximum-of-pages-to-return-when-you-call-to": "Bu /api/pages sayfasını çağırdığınızda gösterilecek maksimum sayfa sayısıdır.",
"this-token-is-for-read-only-and-is-regenerated-every-time-you-install-the-plugin": "Bu token salt okunur amaçlıdır ve eklentiyi her yüklediğinizde yeniden oluşturulur."
}
+10
View File
@@ -0,0 +1,10 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": ""
}
+911
View File
@@ -0,0 +1,911 @@
<?php
class pluginAPI extends Plugin
{
private $method;
// HTTP status applied to the final response. Inner handlers may override it
// by calling setStatus() before returning their result. The body still carries
// the legacy status:'0'|'1' field for backwards compatibility.
private $httpCode = 200;
private $httpMessage = 'OK';
private function setStatus($code)
{
$messages = array(
200 => 'OK',
201 => 'Created',
400 => 'Bad Request',
401 => 'Unauthorized',
403 => 'Forbidden',
404 => 'Not Found',
409 => 'Conflict',
500 => 'Internal Server Error'
);
$this->httpCode = $code;
$this->httpMessage = isset($messages[$code]) ? $messages[$code] : 'Error';
}
public function init()
{
// Generate the API Token (32 bytes = 64 hex chars = 256 bits of entropy)
$token = bin2hex( random_bytes(32) );
$this->dbFields = array(
'token' => $token, // API Token
'numberOfItems' => 15 // Amount of items to return
);
}
public function getToken()
{
return $this->getValue('token');
}
public function form()
{
global $L;
$html = '<div class="alert alert-primary" role="alert">';
$html .= $this->description();
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('URL') . '</label>';
$html .= '<p class="text-muted">' . DOMAIN_BASE . 'api/{endpoint}</p>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('API Token') . '</label>';
$html .= '<input name="token" type="text" dir="auto" value="' . $this->getValue('token') . '">';
$html .= '<span class="tip">' . $L->get('This token is for read only and is regenerated every time you install the plugin') . '</span>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('Amount of pages') . '</label>';
$html .= '<input id="jsnumberOfItems" name="numberOfItems" type="text" dir="auto" value="' . $this->getValue('numberOfItems') . '">';
$html .= '<span class="tip">' . $L->get('This is the maximum of pages to return when you call to') . '</span>';
$html .= '</div>';
return $html;
}
// API HOOKS
// ----------------------------------------------------------------------------
public function beforeAll()
{
global $url;
global $pages;
global $users;
// CHECK URL
// ------------------------------------------------------------
$URI = $this->webhook('api', $returnsAfterURI = true, $fixed = false);
if ($URI === false) {
return false;
}
// METHOD
// ------------------------------------------------------------
$method = $this->getMethod();
// METHOD INPUTS
// ------------------------------------------------------------
$inputs = $this->getMethodInputs();
if (empty($inputs)) {
$this->response(400, 'Bad Request', array('message' => 'Missing method inputs.'));
}
// ENDPOINT PARAMETERS
// ------------------------------------------------------------
$parameters = $this->getEndpointParameters($URI);
if (empty($parameters)) {
$this->response(400, 'Bad Request', array('message' => 'Missing endpoint parameters.'));
}
// API TOKEN
// ------------------------------------------------------------
// Token from the plugin, the user can change it on the settings of the plugin
$tokenAPI = $this->getValue('token');
// Check empty token
if (empty($inputs['token'])) {
$this->response(400, 'Bad Request', array('message' => 'Missing API token.'));
}
// Check if the token is valid
if ($inputs['token'] !== $tokenAPI) {
$this->response(401, 'Unauthorized', array('message' => 'Invalid API token.'));
}
// AUTHENTICATION TOKEN
// ------------------------------------------------------------
$writePermissions = false;
if (!empty($inputs['authentication'])) {
// Get the user with the authentication token, FALSE if it doesn't exist
$username = $users->getByAuthToken($inputs['authentication']);
if ($username !== false) {
try {
$user = new User($username);
if (($user->role() == 'admin') && ($user->enabled())) {
// Loggin the user to create the session
$login = new Login();
$login->setLogin($username, 'admin');
// Enable write permissions
$writePermissions = true;
}
} catch (Exception $e) {
// Continue without permissions
}
}
}
// Clean inputs
// ------------------------------------------------------------
unset($inputs['token']);
unset($inputs['authentication']);
// ENDPOINTS
// ------------------------------------------------------------
// (GET) /api/pages
if (($method === 'GET') && ($parameters[0] === 'pages') && empty($parameters[1])) {
$data = $this->getPages($inputs);
}
// (GET) /api/pages/<key>
elseif (($method === 'GET') && ($parameters[0] === 'pages') && !empty($parameters[1])) {
$pageKey = $parameters[1];
if (isset($parameters[2])) {
$pageKey = $parameters[1] . '/' . $parameters[2];
}
$data = $this->getPage($pageKey);
}
// (PUT) /api/pages/<key>
elseif (($method === 'PUT') && ($parameters[0] === 'pages') && !empty($parameters[1]) && $writePermissions) {
$pageKey = $parameters[1];
$data = $this->editPage($pageKey, $inputs);
}
// (DELETE) /api/pages/<key>
elseif (($method === 'DELETE') && ($parameters[0] === 'pages') && !empty($parameters[1]) && $writePermissions) {
$pageKey = $parameters[1];
$data = $this->deletePage($pageKey);
}
// (POST) /api/pages
elseif (($method === 'POST') && ($parameters[0] === 'pages') && empty($parameters[1]) && $writePermissions) {
$data = $this->createPage($inputs);
}
// (GET) /api/settings
elseif (($method === 'GET') && ($parameters[0] === 'settings') && empty($parameters[1]) && $writePermissions) {
$data = $this->getSettings();
}
// (PUT) /api/settings
elseif (($method === 'PUT') && ($parameters[0] === 'settings') && empty($parameters[1]) && $writePermissions) {
$data = $this->editSettings($inputs);
}
// (POST) /api/images
elseif (($method === 'POST') && ($parameters[0] === 'images') && $writePermissions) {
$data = $this->uploadImage($inputs);
}
// (GET) /api/tags
elseif (($method === 'GET') && ($parameters[0] === 'tags') && empty($parameters[1])) {
$data = $this->getTags();
}
// (GET) /api/tags/<key>
elseif (($method === 'GET') && ($parameters[0] === 'tags') && !empty($parameters[1])) {
$tagKey = $parameters[1];
$data = $this->getTag($tagKey);
}
// (GET) /api/categories
elseif (($method === 'GET') && ($parameters[0] === 'categories') && empty($parameters[1])) {
$data = $this->getCategories();
}
// (GET) /api/categories/<key>
elseif (($method === 'GET') && ($parameters[0] === 'categories') && !empty($parameters[1])) {
$categoryKey = $parameters[1];
$data = $this->getCategory($categoryKey);
}
// (GET) /api/users
elseif (($method === 'GET') && ($parameters[0] === 'users') && empty($parameters[1])) {
$data = $this->getUsers();
}
// (GET) /api/users/<username>
elseif (($method === 'GET') && ($parameters[0] === 'users') && !empty($parameters[1])) {
$username = $parameters[1];
$data = $this->getUser($username);
}
// (GET) /api/files/<page-key>
elseif (($method === 'GET') && ($parameters[0] === 'files') && !empty($parameters[1])) {
$pageKey = $parameters[1];
if (!$this->isValidPageKey($pageKey)) {
$this->response(400, 'Bad Request', array('message' => 'Invalid page key.'));
}
$data = $this->getFiles($pageKey);
}
// (POST) /api/files/<page-key>
elseif (($method === 'POST') && ($parameters[0] === 'files') && !empty($parameters[1]) && $writePermissions) {
$pageKey = $parameters[1];
if (!$this->isValidPageKey($pageKey)) {
$this->response(400, 'Bad Request', array('message' => 'Invalid page key.'));
}
$data = $this->uploadFile($pageKey);
} else {
$this->response(401, 'Unauthorized', array('message' => 'Access denied or invalid endpoint.'));
}
$this->response($this->httpCode, $this->httpMessage, $data);
}
// PRIVATE METHODS
// ----------------------------------------------------------------------------
// Validate page key to prevent path traversal (CWE-22)
private function isValidPageKey($pageKey)
{
if (strpos($pageKey, '..') !== false) {
return false;
}
if (strpos($pageKey, "\0") !== false) {
return false;
}
return true;
}
private function getMethod()
{
// METHODS
// ------------------------------------------------------------
// GET
// POST
// PUT
// DELETE
$this->method = $_SERVER['REQUEST_METHOD'];
return $this->method;
}
private function getMethodInputs()
{
switch ($this->method) {
case "POST":
$inputs = $_POST;
break;
case "GET":
case "DELETE":
$inputs = $_GET;
break;
case "PUT":
$inputs = '';
break;
default:
$inputs = json_encode(array());
break;
}
// Try to get raw/json data
if (empty($inputs)) {
$inputs = file_get_contents('php://input');
}
return $this->cleanInputs($inputs);
}
// Returns an array with key=>value with the inputs
// If the content is JSON is parsed to array
//
// Note: DB-bound values are sanitized by core (Pages::add/edit, Site::set);
// sanitizing again here would double-encode form/query values like
// "Cats & Dogs" into "Cats &amp;amp; Dogs".
private function cleanInputs($inputs)
{
if (is_array($inputs)) {
return $inputs;
}
if (is_string($inputs)) {
$decoded = json_decode($inputs, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return array();
}
return is_array($decoded) ? $decoded : array();
}
return array();
}
private function getEndpointParameters($URI)
{
// ENDPOINT Parameters
// ------------------------------------------------------------
// /api/pages | GET | returns all pages
// /api/pages/{key} | GET | returns the page with the {key}
// /api/pages | POST | create a new page
$URI = ltrim($URI, '/');
$parameters = explode('/', $URI);
// Sanitize parameters
foreach ($parameters as $key => $value) {
$parameters[$key] = Sanitize::html($value);
}
return $parameters;
}
private function response($code = 200, $message = 'OK', $data = array())
{
header('HTTP/1.1 ' . $code . ' ' . $message);
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
$json = json_encode($data);
exit($json);
}
private function getTags()
{
global $tags;
$tmp = array(
'status' => '0',
'message' => 'List of tags.',
'data' => array()
);
foreach ($tags->keys() as $key) {
$tag = $tags->getMap($key);
array_push($tmp['data'], $tag);
}
return $tmp;
}
// Returns the tag information and the pages releated to the tag
// The array with the pages has the complete information of each page
private function getTag($key)
{
try {
$tag = new Tag($key);
} catch (Exception $e) {
$this->setStatus(404);
return array(
'status' => '1',
'message' => 'Tag not found by the key: ' . $key
);
}
$list = array();
foreach ($tag->pages() as $pageKey) {
try {
$page = new Page($pageKey);
array_push($list, $page->json($returnsArray = true));
} catch (Exception $e) {
}
}
$data = $tag->json($returnsArray = true);
$data['pages'] = $list;
return array(
'status' => '0',
'message' => 'Information about the tag and pages related.',
'data' => $data
);
}
private function getPages($args)
{
global $pages;
// Parameters and the default values
$published = (isset($args['published']) ? $args['published'] == 'true' : true);
$static = (isset($args['static']) ? $args['static'] == 'true' : false);
$draft = (isset($args['draft']) ? $args['draft'] == 'true' : false);
$sticky = (isset($args['sticky']) ? $args['sticky'] == 'true' : false);
$scheduled = (isset($args['scheduled']) ? $args['scheduled'] == 'true' : false);
$untagged = (isset($args['untagged']) ? $args['untagged'] == 'true' : false);
$numberOfItems = (isset($args['numberOfItems']) ? (int)$args['numberOfItems'] : (int)$this->getValue('numberOfItems'));
$pageNumber = (isset($args['pageNumber']) ? (int)$args['pageNumber'] : 1);
// Clamp to safe values. -1 is the documented "return all" sentinel for
// numberOfItems; anything else <=0 falls back to the plugin default and
// then to a hard fallback so getList() can never receive 0.
if ($pageNumber < 1) {
$pageNumber = 1;
}
if ($numberOfItems === 0) {
$numberOfItems = (int)$this->getValue('numberOfItems');
}
if ($numberOfItems === 0 || $numberOfItems < -1) {
$numberOfItems = 15;
}
$list = $pages->getList($pageNumber, $numberOfItems, $published, $static, $sticky, $draft, $scheduled);
// getList() returns false when pageNumber is past the end; treat as empty.
if ($list === false) {
$list = array();
}
// total reflects the count of pages matching the type filters; the
// untagged filter is applied to the page slice below, so it is not
// reflected in this total.
$total = $pages->countByType($published, $static, $sticky, $draft, $scheduled);
$hasMore = ($numberOfItems > 0) && (($pageNumber * $numberOfItems) < $total);
$tmp = array(
'status' => '0',
'message' => 'List of pages',
'numberOfItems' => $numberOfItems,
'meta' => array(
'total' => $total,
'pageNumber' => $pageNumber,
'pageSize' => $numberOfItems,
'hasMore' => $hasMore
),
'data' => array()
);
foreach ($list as $pageKey) {
try {
// Create the page object from the page key
$page = new Page($pageKey);
if ($untagged) {
if (empty($page->tags())) {
// Push the page to the data array for the response
array_push($tmp['data'], $page->json($returnsArray = true));
}
} else {
array_push($tmp['data'], $page->json($returnsArray = true));
}
} catch (Exception $e) {
// Continue
}
}
return $tmp;
}
private function getPage($key)
{
try {
$page = new Page($key);
return array(
'status' => '0',
'message' => 'Page filtered by key: ' . $key,
'data' => $page->json($returnsArray = true)
);
} catch (Exception $e) {
$this->setStatus(404);
return array(
'status' => '1',
'message' => 'Page not found.'
);
}
}
private function createPage($args)
{
// This function is defined on functions.php
$key = createPage($args);
if ($key === false) {
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'Error trying to create the new page.'
);
}
$this->setStatus(201);
try {
$page = new Page($key);
return array(
'status' => '0',
'message' => 'Page created.',
'data' => $page->json($returnsArray = true)
);
} catch (Exception $e) {
// The page was created but failed to load. Fall back to the legacy
// minimal payload so the caller still gets the key.
return array(
'status' => '0',
'message' => 'Page created.',
'data' => array('key' => $key)
);
}
}
private function editPage($key, $args)
{
global $pages;
if (!$pages->exists($key)) {
$this->setStatus(404);
return array(
'status' => '1',
'message' => 'Page not found.'
);
}
$args['key'] = $key;
$newKey = editPage($args);
if ($newKey === false) {
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'Error trying to edit the page.'
);
}
try {
$page = new Page($newKey);
return array(
'status' => '0',
'message' => 'Page edited.',
'data' => $page->json($returnsArray = true)
);
} catch (Exception $e) {
// The page was edited but failed to load. Fall back to the legacy
// minimal payload so the caller still gets the key.
return array(
'status' => '0',
'message' => 'Page edited.',
'data' => array('key' => $newKey)
);
}
}
private function deletePage($key)
{
global $pages;
if (!$pages->exists($key)) {
$this->setStatus(404);
return array(
'status' => '1',
'message' => 'Page not found.'
);
}
if (deletePage($key)) {
return array(
'status' => '0',
'message' => 'Page deleted.'
);
}
$this->setStatus(500);
return array(
'status' => '1',
'message' => 'Error trying to delete the page.'
);
}
/*
| Upload an image and generate the thumbnails
| Returns the image and thumbnail URL
|
| @inputs array
| @inputs['uuid'] string Page UUID
| @_FILE array https://www.php.net/manual/en/reserved.variables.files.php
|
| @return array
*/
private function uploadImage($inputs)
{
// Set upload directory
if (isset($inputs['uuid']) && IMAGE_RESTRICT) {
if (!$this->isValidPageKey($inputs['uuid'])) {
$this->setStatus(400);
return array('status' => '1', 'message' => 'Invalid UUID.');
}
$imageDirectory = PATH_UPLOADS_PAGES . $inputs['uuid'] . DS;
$thumbnailDirectory = $imageDirectory . 'thumbnails' . DS;
$imageEndpoint = DOMAIN_UPLOADS_PAGES . $inputs['uuid'] . '/';
$thumbnailEndpoint = $imageEndpoint . 'thumbnails' . '/';
if (!Filesystem::directoryExists($thumbnailDirectory)) {
Filesystem::mkdir($thumbnailDirectory, true);
}
} else {
$imageDirectory = PATH_UPLOADS;
$thumbnailDirectory = PATH_UPLOADS_THUMBNAILS;
$imageEndpoint = DOMAIN_UPLOADS;
$thumbnailEndpoint = DOMAIN_UPLOADS_THUMBNAILS;
}
if (!isset($_FILES['image'])) {
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'No image sent.'
);
}
if ($_FILES['image']['error'] != 0) {
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'Error uploading the image, maximum load file size allowed: ' . ini_get('upload_max_filesize')
);
}
// Move from PHP tmp file to Bludit tmp directory
Filesystem::mv($_FILES['image']['tmp_name'], PATH_TMP . $_FILES['image']['name']);
// Transform image and create thumbnails
$image = transformImage(PATH_TMP . $_FILES['image']['name'], $imageDirectory, $thumbnailDirectory);
if ($image) {
$filename = Filesystem::filename($image);
return array(
'status' => '0',
'message' => 'Image uploaded.',
'image' => $imageEndpoint . $filename,
'thumbnail' => $thumbnailEndpoint . $filename
);
}
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'Image extension not allowed.'
);
}
/*
| Get the settings
|
| @args array
|
| @return array
*/
private function getSettings()
{
global $site;
return array(
'status' => '0',
'message' => 'Settings.',
'data' => $site->get()
);
}
/*
| Edit the settings
| You can edit any field defined in the class site.class.php variable $dbFields
|
| @args array
|
| @return array
*/
private function editSettings($args)
{
if (editSettings($args)) {
return array(
'status' => '0',
'message' => 'Settings edited.'
);
}
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'Error trying to edit the settings.'
);
}
/*
| Returns the categories in the system
| Included the category name, key, description and the list of pages
| The list of pages are the page's key
|
| @return array
*/
private function getCategories()
{
global $categories;
$tmp = array(
'status' => '0',
'message' => 'List of categories.',
'data' => array()
);
foreach ($categories->keys() as $key) {
$category = $categories->getMap($key);
array_push($tmp['data'], $category);
}
return $tmp;
}
/*
| Returns information about the category and pages related
| The pages are expanded which mean the title, content and more fields are returned in the query
| This can degrade the performance
|
| @key string Category key
|
| @return array
*/
private function getCategory($key)
{
try {
$category = new Category($key);
} catch (Exception $e) {
$this->setStatus(404);
return array(
'status' => '1',
'message' => 'Category not found by the key: ' . $key
);
}
$list = array();
foreach ($category->pages() as $pageKey) {
try {
$page = new Page($pageKey);
array_push($list, $page->json($returnsArray = true));
} catch (Exception $e) {
}
}
$data = $category->json($returnsArray = true);
$data['pages'] = $list;
return array(
'status' => '0',
'message' => 'Information about the category and pages related.',
'data' => $data
);
}
/*
| Returns the user profile
|
| @username string Username
|
| @return array
*/
private function getUser($username)
{
try {
$user = new User($username);
} catch (Exception $e) {
$this->setStatus(404);
return array(
'status' => '1',
'message' => 'User not found by username: ' . $username
);
}
$data = $user->json($returnsArray = true);
return array(
'status' => '0',
'message' => 'User profile.',
'data' => $data
);
}
/*
| Returns all the users
|
| @return array
*/
private function getUsers()
{
global $users;
$data = array();
foreach ($users->db as $username => $profile) {
try {
$user = new User($username);
$data[$username] = $user->json($returnsArray = true);
} catch (Exception $e) {
continue;
}
}
return array(
'status' => '0',
'message' => 'Users profiles.',
'data' => $data
);
}
/*
| Returns all files uploaded for a specific page, includes any type of file.
|
| @return array
*/
private function getFiles($pageKey)
{
$chunk = false;
$sortByDate = true;
$path = PATH_UPLOADS_PAGES . $pageKey . DS;
$listFiles = Filesystem::listFiles($path, '*', '*', $sortByDate, $chunk);
$files = array();
foreach ($listFiles as $file) {
$info = array('thumbnail' => '');
$info['file'] = $file;
$info['filename'] = basename($file);
$info['mime'] = Filesystem::mimeType($file);
$info['size'] = Filesystem::getSize($file);
// Check if thumbnail exists for the file
$thumbnail = $path . 'thumbnails' . DS . $info['filename'];
if (Filesystem::fileExists($thumbnail)) {
$info['thumbnail'] = $thumbnail;
}
array_push($files, $info);
}
return array(
'status' => '0',
'message' => 'Files for the page key: ' . $pageKey,
'data' => $files
);
}
/*
| Upload a file to a particular page
| Returns the file URL
|
| @inputs array
| @inputs['uuid'] string Page UUID
| @_FILE array https://www.php.net/manual/en/reserved.variables.files.php
|
| @return array
*/
private function uploadFile($pageKey)
{
if (!isset($_FILES['file'])) {
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'File not sent.'
);
}
if ($_FILES['file']['error'] != 0) {
$this->setStatus(400);
return array(
'status' => '1',
'message' => 'Error uploading the file.'
);
}
$filename = $_FILES['file']['name'];
// Block dotfiles
if (strpos($filename, '.') === 0) {
$this->setStatus(400);
return array('status' => '1', 'message' => 'File type not allowed.');
}
// Check file extension
$fileExtension = Filesystem::extension($filename);
$fileExtension = Text::lowercase($fileExtension);
if (!in_array($fileExtension, $GLOBALS['ALLOWED_FILE_EXTENSIONS'])) {
$this->setStatus(400);
return array('status' => '1', 'message' => 'File type not allowed.');
}
// Sanitize filename to prevent issues with special characters
$filenameWithoutExt = Filesystem::filename($filename);
$filenameWithoutExt = Text::removeSpecialCharacters($filenameWithoutExt, '-');
$filenameWithoutExt = Text::removeQuotes($filenameWithoutExt);
$filenameWithoutExt = Text::removeSpaces($filenameWithoutExt, '-');
$filename = $filenameWithoutExt . '.' . $fileExtension;
$absoluteURL = DOMAIN_UPLOADS_PAGES . $pageKey . '/' . $filename;
$absolutePath = PATH_UPLOADS_PAGES . $pageKey . DS . $filename;
if (Filesystem::mv($_FILES['file']['tmp_name'], $absolutePath)) {
return array(
'status' => '0',
'message' => 'File uploaded.',
'filename' => $filename,
'absolutePath' => $absolutePath,
'absoluteURL' => $absoluteURL
);
}
$this->setStatus(500);
return array(
'status' => '1',
'message' => 'Error moving the file to the final path.'
);
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"plugin-data": {
"description": "Brug af canonical URLs kan hjælpe med at informere søgemaskiner om hvilke URLs der har identisk indhold.",
"name": "Canonical"
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "Kennzeichnung von Seiten mit kanonischen Links, um Dublicate Content bei der Erfassung durch Suchmaschinen zu verhindern."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "Kennzeichnung von Seiten mit kanonischen Links, um Dublicate Content bei der Erfassung durch Suchmaschinen zu verhindern."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "Using canonical URLs can help to inform search engines which URLs have identical content."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "El uso de URL canónicas ayuda a los motores de búsqueda qué URLs tienen contenido idéntico."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "لینک استاندارد",
"description": "با استفاده از آدرس‌های وب استاندارد می‌توانید به اطلاع موتورهای جستجو برسانید که کدامیک از آدرس وب ها داری محتوای یکسانی هستند."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "URL Canonique",
"description": "L'utilisation d'URL canoniques permet d'indiquer aux moteurs de recherche quelles URL ont un contenu identique."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "L'utilizzo degli URLS canonici può aiutare i motori di ricerca quali URL hanno un contenuto identico."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "カノニカル(正規化)URLを使用すると、検索エンジンに、どのURLのコンテンツが同一コンテンツであるかを通知できます。"
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonieke URLs",
"description": "Het gebruik van canonieke URLs kan helpen bij het informeren van zoekmachines over welke URLs dezelfde inhoud hebben."
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Canonical",
"description": "Плагин для использоания канонических URL-адресов. Использование канонических URL-адресов может помочь сообщить поисковым системам, какие URL-адреса имеют идентичный контент."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Канонические URL-адреса",
"description": "Использование канонических URL-адресов может помочь поисковым системам грамотно идентифицировать URL-адреса страниц с дублирующимся содержанием."
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": ""
}
+87
View File
@@ -0,0 +1,87 @@
<?php
class pluginCanonical extends Plugin {
public function siteHead()
{
global $url;
global $page;
global $WHERE_AM_I;
$html = '';
$canonical = '';
switch ($WHERE_AM_I) {
case 'home':
// Handle pagination on homepage
$pageNumber = $url->pageNumber();
if ($pageNumber > 1) {
$canonical = DOMAIN_BASE . 'page/' . $pageNumber . '/';
} else {
$canonical = DOMAIN_BASE;
}
break;
case 'page':
$canonical = $page->permalink($absolute = true);
break;
case 'category':
// Category pages
$categoryKey = $url->slug();
$canonical = DOMAIN_CATEGORIES . $categoryKey . '/';
$pageNumber = $url->pageNumber();
if ($pageNumber > 1) {
$canonical .= 'page/' . $pageNumber . '/';
}
break;
case 'tag':
// Tag pages
$tagKey = $url->slug();
$canonical = DOMAIN_TAGS . $tagKey . '/';
$pageNumber = $url->pageNumber();
if ($pageNumber > 1) {
$canonical .= 'page/' . $pageNumber . '/';
}
break;
default:
// For any other page type, use current URI
$canonical = DOMAIN_BASE . ltrim($url->uri(), '/');
break;
}
if (!empty($canonical)) {
$html .= '<link rel="canonical" href="' . htmlspecialchars($canonical, ENT_QUOTES, 'UTF-8') . '">' . PHP_EOL;
// Add prev/next for paginated content (helps search engines)
$pageNumber = $url->pageNumber();
if ($pageNumber > 1) {
// Previous page
if ($pageNumber === 2) {
$prevUrl = preg_replace('/page\/\d+\/?$/', '', $canonical);
} else {
$prevUrl = preg_replace('/page\/\d+\/?$/', 'page/' . ($pageNumber - 1) . '/', $canonical);
}
$html .= '<link rel="prev" href="' . htmlspecialchars($prevUrl, ENT_QUOTES, 'UTF-8') . '">' . PHP_EOL;
}
// Next page (only if more content exists)
// This requires checking if there's a next page of content
global $content;
global $site;
if (isset($content) && is_array($content) && count($content) >= $site->itemsPerPage()) {
$nextUrl = preg_replace('/page\/\d+\/?$/', '', $canonical);
if ($pageNumber < 1) {
$nextUrl .= 'page/2/';
} else {
$nextUrl = preg_replace('/page\/\d+\/?$/', 'page/' . ($pageNumber + 1) . '/', $canonical);
}
$html .= '<link rel="next" href="' . htmlspecialchars($nextUrl, ENT_QUOTES, 'UTF-8') . '">' . PHP_EOL;
}
}
return $html;
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"hide-categories-without-content": "Skjul kategorier uden indhold",
"plugin-data": {
"description": "Viser alle kategorier på sidepanelet.",
"name": "Categories"
}
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Kategorien",
"description": "Zeigt alle Kategorien in der Seitenleiste (bei Themes mit einer Seitenleiste)."
},
"hide-categories-without-content": "Kategorien ohne Inhalte ausblenden"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Kategorien",
"description": "Zeigt alle Kategorien in der Seitenleiste (bei Themes mit einer Seitenleiste)."
},
"hide-categories-without-content": "Kategorien ohne Inhalte ausblenden"
}
+8
View File
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Categories",
"description": "Shows all categories on the sidebar."
},
"hide-categories-without-content": "Hide Categories without content"
}
+8
View File
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Categorías",
"description": "Muestra todas las categorías en la barra lateral."
},
"hide-categories-without-content": "Ocultar categorías sin contenido"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "مجموعه ها",
"description": "نمایش تمام مجموعه ها در نوارکناری."
},
"hide-categories-without-content": "پنهان کردن مجموعه های خالی از محتوا"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Catégories",
"description": "Affiche toutes les catégories sur la barre latérale."
},
"hide-categories-without-content": "Masquer les catégories sans contenu."
}
+8
View File
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Categorie",
"description": "Visualizza tutte le categorie nella barra laterale."
},
"hide-categories-without-content": "Nascondi categorie senza contenuto"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Categories",
"description": "サイドバーにすべてのカテゴリを表示します。"
},
"hide-categories-without-content": "コンテンツのないカテゴリを非表示にする"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Categorie&euml;n",
"description": "Toont alle categorie&euml;n in de zijbalk."
},
"hide-categories-without-content": "Categorie&euml;n zonder inhoud verbergen"
}
+8
View File
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Категории",
"description": "Показывает все категории на боковой панели."
},
"hide-categories-without-content": "Скрывать пустые категории"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Kategoriler",
"description": "Tüm kategorileri kenar çubuğunda göster."
},
"hide-categories-without-content": "İçeriksiz kategorileri gizle"
}
@@ -0,0 +1,8 @@
{
"plugin-data":
{
"name": "Категорії",
"description": "Показує всі категорії на бічній панелі."
},
"hide-categories-without-content": "Сховати категорії без вмісту"
}
+10
View File
@@ -0,0 +1,10 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": ""
}
+72
View File
@@ -0,0 +1,72 @@
<?php
class pluginCategories extends Plugin
{
public function init()
{
// Fields and default values for the database of this plugin
$this->dbFields = array(
'label' => 'Categories',
'hideCero' => true
);
}
// Method called on the settings of the plugin on the admin area
public function form()
{
global $L;
$html = '<div class="alert alert-primary" role="alert">';
$html .= $this->description();
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('Label') . '</label>';
$html .= '<input name="label" type="text" dir="auto" value="' . $this->getValue('label') . '">';
$html .= '<span class="tip">' . $L->get('This title is almost always used in the sidebar of the site') . '</span>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('Hide Categories without content') . '</label>';
$html .= '<select name="hideCero">';
$html .= '<option value="true" ' . ($this->getValue('hideCero') === true ? 'selected' : '') . '>' . $L->get('Enabled') . '</option>';
$html .= '<option value="false" ' . ($this->getValue('hideCero') === false ? 'selected' : '') . '>' . $L->get('Disabled') . '</option>';
$html .= '</select>';
$html .= '</div>';
return $html;
}
// Method called on the sidebar of the website
public function siteSidebar()
{
global $L;
global $categories;
// HTML for sidebar
$html = '<div class="plugin plugin-categories">';
$html .= '<h2 class="plugin-label">' . $this->getValue('label') . '</h2>';
$html .= '<div class="plugin-content">';
$html .= '<ul>';
// By default, the database of categories is alphanumeric sorted
foreach ($categories->db as $key => $fields) {
$count = count($fields['list']);
if (!$this->getValue('hideCero') || $count > 0) {
$html .= '<li>';
$html .= '<a href="' . DOMAIN_CATEGORIES . $key . '">';
$html .= $fields['name'];
$html .= ' (' . count($fields['list']) . ')';
$html .= '</a>';
$html .= '</li>';
}
}
$html .= '</ul>';
$html .= '</div>';
$html .= '</div>';
return $html;
}
}
@@ -0,0 +1,6 @@
{
"plugin-data": {
"description": "Definer kode for de brugerdefinerede felter, og fortolk indholdet af siderne.",
"name": "Custom fields parser"
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Custom fields parser",
"description": "Define code for the custom fields and parse the content of the pages."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "تحلیل‌گر کادر سفارشی",
"description": "برای کادرهای سفارشی کد تعریف کرده و محتوای صفحات را تحلیل کنید."
}
}
@@ -0,0 +1,7 @@
{
"plugin-data":
{
"name": "Analyseur de champs personnalisés",
"description": "Définissez le code des champs personnalisés et analysez le contenu des pages."
}
}
@@ -0,0 +1,6 @@
{
"plugin-data": {
"name": "Парсер пользовательских полей",
"description": "Ищет код пользовательских полей и отпределяет содержимое страниц в соответствии с найденным кодом."
}
}
@@ -0,0 +1,10 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": ""
}
@@ -0,0 +1,92 @@
<?php
class pluginCustomFieldsParser extends Plugin {
public function init()
{
$this->dbFields = array(
'label'=>'Custom fields parser',
'jsondb'=>json_encode(array())
);
}
public function form()
{
global $L;
global $site;
$html = '<div class="alert alert-primary" role="alert">';
$html .= $this->description();
$html .= '</div>';
$jsondb = $this->getValue('jsondb', false);
$database = json_decode($jsondb, true);
$customFields = $site->customFields();
foreach ($customFields as $field=>$options) {
if ($options['type']=="string") {
$html .= '<div>';
$html .= '<label>'.$options['label'].'</label>';
$html .= '<textarea name="'.$field.'">'.(isset($database[$field])?$database[$field]:'').'</textarea>';
$html .= '</div>';
}
}
return $html;
}
public function post()
{
$this->db['jsondb'] = Sanitize::html(json_encode($_POST));
return $this->save();
}
public function parse($page)
{
$jsondb = $this->getValue('jsondb', false);
$database = json_decode($jsondb, true);
$parsedCode = array();
// Ensure $database is a valid array before iterating
if (is_array($database)) {
foreach ($database as $field=>$code) {
$value = $page->custom($field);
$parsedCode['{{ '.$field.' }}'] = str_replace('{{ value }}', $value, $code);
}
}
$content = $page->contentRaw();
if (!empty($parsedCode)) {
$content = str_replace(array_keys($parsedCode), array_values($parsedCode), $content);
}
// Parse Markdown
if (MARKDOWN_PARSER) {
$parsedown = new Parsedown();
$content = $parsedown->text($content);
}
// Parse img src relative to absolute (with domain)
if (IMAGE_RELATIVE_TO_ABSOLUTE) {
$domain = IMAGE_RESTRICT ? DOMAIN_UPLOADS_PAGES . $page->uuid() . '/' : DOMAIN_UPLOADS;
$content = Text::imgRel2Abs($content, $domain);
}
return $content;
}
public function beforeSiteLoad()
{
if ($GLOBALS['WHERE_AM_I']=='page') {
$GLOBALS['page']->setField('content', $this->parse($GLOBALS['page']));
} else {
foreach ($GLOBALS['content'] as $key=>$page) {
$GLOBALS['content'][$key]->setField('content', $this->parse($GLOBALS['content'][$key]));
}
if (!empty($GLOBALS['content'])) {
$GLOBALS['page'] = $GLOBALS['content'][0];
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"disqus-shortname": "Disqus kortnavn",
"enable-disqus-on-pages": "Disqus på sider",
"enable-disqus-on-static-pages": "Disqus på statiske sider",
"enable-disqus-on-sticky-pages": "Disqus på fastgjorde sider",
"get-the-shortname-from-the-disqus-general-settings": "Hent det korte navn fra Disqus generelle indstillinger",
"plugin-data": {
"description": "Disqus er en kommentar hostingstjeneste til websteder.<br>Det er nødvendigt at være registreret på <a href=\"https://disqus.com\">Disqus</a> for at bruge denne service.",
"name": "Disqus"
}
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "Disqus ist eine Kommentar-Plattform für Websites. Um das Plugin verwenden zu können, muss ein Konto bei <a href=\"https://disqus.com\">Disqus</a> eingerichtet werden."
},
"disqus-shortname": "Disqus-Kurzname (Shortname)",
"enable-disqus-on-pages": "Disqus auf Seiten",
"enable-disqus-on-static-pages": "Disqus auf statischen Seiten",
"enable-disqus-on-sticky-pages": "Disqus bei fixierten Inhalten",
"get-the-shortname-from-the-disqus-general-settings": "Der Kurzname wird bei Disqus unter \"Settings\" > \"General\" angezeigt."
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "Disqus ist eine Kommentar-Plattform für Websites. Um das Plugin verwenden zu können, muss ein Konto bei <a href=\"https://disqus.com\">Disqus</a> eingerichtet werden."
},
"disqus-shortname": "Disqus-Kurzname (Shortname)",
"enable-disqus-on-pages": "Disqus auf Seiten",
"enable-disqus-on-static-pages": "Disqus auf statischen Seiten",
"enable-disqus-on-sticky-pages": "Disqus bei fixierten Inhalten",
"get-the-shortname-from-the-disqus-general-settings": "Der Kurzname wird bei Disqus unter \"Settings\" > \"General\" angezeigt."
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "Disqus is a comment hosting service for web sites.<br>It's necessary to be registered on <a href=\"https://disqus.com\">Disqus</a> to use this service."
},
"disqus-shortname": "Disqus shortname",
"enable-disqus-on-pages": "Disqus on pages",
"enable-disqus-on-static-pages": "Disqus on static pages",
"enable-disqus-on-sticky-pages": "Disqus on sticky pages",
"get-the-shortname-from-the-disqus-general-settings": "Get the shortname from the Disqus general settings"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "Disqus es un servicio de comentarios online.<br>Es necesario registrarse en <a href=\"https://disqus.com\">Disqus</a> antes de utilizar este plugin."
},
"disqus-shortname": "Disqus shortname",
"enable-disqus-on-pages": "Disqus en página",
"enable-disqus-on-static-pages": "Disqus en página estaticas",
"enable-disqus-on-sticky-pages": "Disqus en página sticky",
"get-the-shortname-from-the-disqus-general-settings": "Puede obtener el shortname en la página de configuración de Disqus."
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "دیسکاس",
"description": "دیسکاس یک سرویس اینترنتی ارسال دیدگاه برای وبسایت ها می‌باشد.<br>برای استفاده از این سرویس لازم است که در <a href=\"https://disqus.com\">Disqus</a> ثبت نام کنید."
},
"disqus-shortname": "نام کوتاه دیسکاس",
"enable-disqus-on-pages": "دیسکاس در صفحات",
"enable-disqus-on-static-pages": "دیسکاس در صفحات استاتیک",
"enable-disqus-on-sticky-pages": "دیسکاس در صفحات چسبنده",
"get-the-shortname-from-the-disqus-general-settings": "دریافت نام کوتاه از تنظیمات عمومی دیسکاس"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus système de commentaire",
"description": "Disqus est un service Web de discussion et de commentaires d'articles centralisé avec authentification unique. Il est nécessaire de sinscrire sur Disqus.com avant dutiliser ce plugin."
},
"disqus-shortname": "Votre ID Disqus",
"enable-disqus-on-pages": "Disqus sur les pages",
"enable-disqus-on-static-pages": "Disqus sur les pages statiques",
"enable-disqus-on-sticky-pages": "Disqus sur les pages épinglées",
"get-the-shortname-from-the-disqus-general-settings": "Obtenez votre ID à partir des paramètres généraux de Disqus."
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "Disqus è un servizio di hosting per i commenti sui siti web.<br>E' neccesario essere resitrati su <a href=\"https://disqus.com\">Disqus</a> per utilizzare questo servizio."
},
"disqus-shortname": "Nome Breve Disqus ",
"enable-disqus-on-pages": "Disqus sulle pagine",
"enable-disqus-on-static-pages": "Disqus sulle pagine statiche",
"enable-disqus-on-sticky-pages": "Disqus sulle pagine sticky",
"get-the-shortname-from-the-disqus-general-settings": "Acquisisci il nome utente da utilizzare dalle impostazioni generali di Disqus"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "DisqusはWebサイト向けのコメントホスティングサービスです。このサービスを利用するには、<a href=\"https:\/\/disqus.com\">Disqus<\/a>に登録する必要があります。"
},
"disqus-shortname": "Disqusショートネーム",
"enable-disqus-on-pages": "ページにDisqusを使用",
"enable-disqus-on-static-pages": "固定ページにDisqusを使用",
"enable-disqus-on-sticky-pages": "先頭固定ページにDisqusを使用",
"get-the-shortname-from-the-disqus-general-settings": "Disqus一般設定からショートネームを取得します"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus",
"description": "Disqus is hosting service om reacties in websites te implementeren.<br>Registratie op Disqus.com is nodig voordat deze plugin gebruikt kan gebruiken."
},
"disqus-shortname": "Disqus shortname",
"enable-disqus-on-pages": "Disqus op pagina's tonen",
"enable-disqus-on-static-pages": "Disqus on statische pagina's tonen",
"enable-disqus-on-sticky-pages": "Disqus on vastgezette pagina's tonen",
"get-the-shortname-from-the-disqus-general-settings": "De shortname is te verkrijgen via de algemene instellingen van Disqus"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "System komentarzy - Disqus",
"description": "System komentarzy Disqus przechowuje komentarze dla serwisów internetowych. Korzystanie z tej wtyczki wymaga rejestracji w serwisie disqus.com."
},
"disqus-shortname": "Nazwa użytkownika Disqus",
"enable-disqus-on-pages": "Disqus on pages",
"enable-disqus-on-static-pages": "Disqus on static pages",
"enable-disqus-on-sticky-pages": "Disqus on sticky pages",
"get-the-shortname-from-the-disqus-general-settings": "Get the shortname from the Disqus general settings"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Комментарии Disqus",
"description": "Disqus это сервис комментариев для сайтов и блогов. Необходимо зарегистрироваться на Disqus.com перед тем как использовать плагина."
},
"disqus-shortname": "Краткое имя Disqus",
"enable-disqus-on-pages": "Disqus для страниц",
"enable-disqus-on-static-pages": "Disqus для статических страниц",
"enable-disqus-on-sticky-pages": "Disqus для прикреплённых страниц",
"get-the-shortname-from-the-disqus-general-settings": "Получить краткое имя со страницы общих настроек Disqus"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Disqus Yorum Sistemi",
"description": "Disqus siteler için yorum barındırması yapan bir firmadır. Eklentiyi kullanmadan önce Disqus.com adresine kayıt olmanız gerekmektedir."
},
"disqus-shortname": "Disqus shortname",
"enable-disqus-on-pages": "Disqus on pages",
"enable-disqus-on-static-pages": "Disqus on static pages",
"enable-disqus-on-sticky-pages": "Disqus on sticky pages",
"get-the-shortname-from-the-disqus-general-settings": "Get the shortname from the Disqus general settings"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "Система коментарів Disqus",
"description": "Disqus надає послуги хостингу коментарів для веб-сайтів. Необхідно зареєструватися на Disqus.com перед використанням цього плагіна."
},
"disqus-shortname": "Коротке ім'я в Disqus",
"enable-disqus-on-pages": "Disqus on pages",
"enable-disqus-on-static-pages": "Disqus on static pages",
"enable-disqus-on-sticky-pages": "Disqus on sticky pages",
"get-the-shortname-from-the-disqus-general-settings": "Get the shortname from the Disqus general settings"
}
+10
View File
@@ -0,0 +1,10 @@
{
"author": "Bludit",
"email": "",
"website": "https://plugins.bludit.com",
"version": "3.22.0",
"releaseDate": "2026-05-10",
"license": "MIT",
"compatible": "3.22",
"notes": ""
}
+112
View File
@@ -0,0 +1,112 @@
<?php
class pluginDisqus extends Plugin
{
public function init()
{
$this->dbFields = array(
'shortname' => '',
'enablePages' => true,
'enableStatic' => true,
'enableSticky' => true
);
}
public function form()
{
global $L;
$html = '<div class="alert alert-primary" role="alert">';
$html .= $this->description();
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('disqus-shortname') . '</label>';
$html .= '<input name="shortname" id="jsshortname" type="text" dir="auto" value="' . $this->getValue('shortname') . '">';
$html .= '<span class="tip">' . $L->get('Get the shortname from the Disqus general settings') . '</span>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('enable-disqus-on-pages') . '</label>';
$html .= '<select name="enablePages">';
$html .= '<option value="true" ' . ($this->getValue('enablePages') === true ? 'selected' : '') . '>' . $L->get('enabled') . '</option>';
$html .= '<option value="false" ' . ($this->getValue('enablePages') === false ? 'selected' : '') . '>' . $L->get('disabled') . '</option>';
$html .= '</select>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('enable-disqus-on-static-pages') . '</label>';
$html .= '<select name="enableStatic">';
$html .= '<option value="true" ' . ($this->getValue('enableStatic') === true ? 'selected' : '') . '>' . $L->get('enabled') . '</option>';
$html .= '<option value="false" ' . ($this->getValue('enableStatic') === false ? 'selected' : '') . '>' . $L->get('disabled') . '</option>';
$html .= '</select>';
$html .= '</div>';
$html .= '<div>';
$html .= '<label>' . $L->get('enable-disqus-on-sticky-pages') . '</label>';
$html .= '<select name="enableSticky">';
$html .= '<option value="true" ' . ($this->getValue('enableSticky') === true ? 'selected' : '') . '>' . $L->get('enabled') . '</option>';
$html .= '<option value="false" ' . ($this->getValue('enableSticky') === false ? 'selected' : '') . '>' . $L->get('disabled') . '</option>';
$html .= '</select>';
$html .= '</div>';
return $html;
}
public function pageEnd()
{
global $url;
global $WHERE_AM_I;
// Do not show disqus on page not found
if ($url->notFound()) {
return false;
}
if ($WHERE_AM_I === 'page') {
global $page;
if ($page->published() && $this->getValue('enablePages')) {
return $this->javascript();
}
if ($page->isStatic() && $this->getValue('enableStatic')) {
return $this->javascript();
}
if ($page->sticky() && $this->getValue('enableSticky')) {
return $this->javascript();
}
}
return false;
}
private function javascript()
{
global $page;
$pageURL = $page->permalink();
$pageID = $page->uuid();
$shortname = $this->getValue('shortname');
$code = <<<EOF
<!-- Disqus plugin -->
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {
this.page.url = '$pageURL';
this.page.identifier = '$pageID';
};
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://$shortname.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<!-- /Disqus plugin -->
EOF;
return $code;
}
}
+5
View File
@@ -0,0 +1,5 @@
.editor-toolbar { background: #f1f1f1; border-radius: 0 !important; font-size: 1.5em;}
.editor-toolbar::before { margin-bottom: 2px !important }
.editor-toolbar::after { margin-top: 2px !important }
.CodeMirror, .CodeMirror-scroll { flex:1; border-radius: 0 !important; }
.editor-toolbar .fa { color: #555;}
+903
View File
@@ -0,0 +1,903 @@
/**
* easymde v2.18.0
* Copyright Jeroen Akkerman
* @link https://github.com/ionaru/easy-markdown-editor
* @license MIT
*/
.CodeMirror {
font-family: monospace;
height: 300px;
color: #000;
direction: ltr
}
.CodeMirror-lines {
padding: 4px 0
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
padding: 0 4px
}
.CodeMirror-gutter-filler,
.CodeMirror-scrollbar-filler {
background-color: #fff
}
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap
}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap
}
.CodeMirror-guttermarker {
color: #000
}
.CodeMirror-guttermarker-subtle {
color: #999
}
.CodeMirror-cursor {
border-left: 1px solid #000;
border-right: none;
width: 0
}
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0 !important;
background: #7e7
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1
}
.cm-fat-cursor .CodeMirror-line::selection,
.cm-fat-cursor .CodeMirror-line>span::selection,
.cm-fat-cursor .CodeMirror-line>span>span::selection {
background: 0 0
}
.cm-fat-cursor .CodeMirror-line::-moz-selection,
.cm-fat-cursor .CodeMirror-line>span::-moz-selection,
.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection {
background: 0 0
}
.cm-fat-cursor {
caret-color: transparent
}
@-moz-keyframes blink {
50% {
background-color: transparent
}
}
@-webkit-keyframes blink {
50% {
background-color: transparent
}
}
@keyframes blink {
50% {
background-color: transparent
}
}
.cm-tab {
display: inline-block;
text-decoration: inherit
}
.CodeMirror-rulers {
position: absolute;
left: 0;
right: 0;
top: -50px;
bottom: 0;
overflow: hidden
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
top: 0;
bottom: 0;
position: absolute
}
.cm-s-default .cm-header {
color: #00f
}
.cm-s-default .cm-quote {
color: #090
}
.cm-negative {
color: #d44
}
.cm-positive {
color: #292
}
.cm-header,
.cm-strong {
font-weight: 700
}
.cm-em {
font-style: italic
}
.cm-link {
text-decoration: underline
}
.cm-strikethrough {
text-decoration: line-through
}
.cm-s-default .cm-keyword {
color: #708
}
.cm-s-default .cm-atom {
color: #219
}
.cm-s-default .cm-number {
color: #164
}
.cm-s-default .cm-def {
color: #00f
}
.cm-s-default .cm-variable-2 {
color: #05a
}
.cm-s-default .cm-type,
.cm-s-default .cm-variable-3 {
color: #085
}
.cm-s-default .cm-comment {
color: #a50
}
.cm-s-default .cm-string {
color: #a11
}
.cm-s-default .cm-string-2 {
color: #f50
}
.cm-s-default .cm-meta {
color: #555
}
.cm-s-default .cm-qualifier {
color: #555
}
.cm-s-default .cm-builtin {
color: #30a
}
.cm-s-default .cm-bracket {
color: #997
}
.cm-s-default .cm-tag {
color: #170
}
.cm-s-default .cm-attribute {
color: #00c
}
.cm-s-default .cm-hr {
color: #999
}
.cm-s-default .cm-link {
color: #00c
}
.cm-s-default .cm-error {
color: red
}
.cm-invalidchar {
color: red
}
.CodeMirror-composing {
border-bottom: 2px solid
}
div.CodeMirror span.CodeMirror-matchingbracket {
color: #0b0
}
div.CodeMirror span.CodeMirror-nonmatchingbracket {
color: #a22
}
.CodeMirror-matchingtag {
background: rgba(255, 150, 0, .3)
}
.CodeMirror-activeline-background {
background: #e8f2ff
}
.CodeMirror {
position: relative;
overflow: hidden;
background: #fff
}
.CodeMirror-scroll {
overflow: scroll !important;
margin-bottom: -50px;
margin-right: -50px;
padding-bottom: 50px;
height: 100%;
outline: 0;
position: relative;
z-index: 0
}
.CodeMirror-sizer {
position: relative;
border-right: 50px solid transparent
}
.CodeMirror-gutter-filler,
.CodeMirror-hscrollbar,
.CodeMirror-scrollbar-filler,
.CodeMirror-vscrollbar {
position: absolute;
z-index: 6;
display: none;
outline: 0
}
.CodeMirror-vscrollbar {
right: 0;
top: 0;
overflow-x: hidden;
overflow-y: scroll
}
.CodeMirror-hscrollbar {
bottom: 0;
left: 0;
overflow-y: hidden;
overflow-x: scroll
}
.CodeMirror-scrollbar-filler {
right: 0;
bottom: 0
}
.CodeMirror-gutter-filler {
left: 0;
bottom: 0
}
.CodeMirror-gutters {
position: absolute;
left: 0;
top: 0;
min-height: 100%;
z-index: 3
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -50px
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: 0 0 !important;
border: none !important
}
.CodeMirror-gutter-background {
position: absolute;
top: 0;
bottom: 0;
z-index: 4
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4
}
.CodeMirror-gutter-wrapper ::selection {
background-color: transparent
}
.CodeMirror-gutter-wrapper ::-moz-selection {
background-color: transparent
}
.CodeMirror-lines {
cursor: text;
min-height: 1px
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
border-width: 0;
background: 0 0;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual
}
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal
}
.CodeMirror-linebackground {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 0
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
padding: .1px
}
.CodeMirror-rtl pre {
direction: rtl
}
.CodeMirror-code {
outline: 0
}
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber,
.CodeMirror-scroll,
.CodeMirror-sizer {
-moz-box-sizing: content-box;
box-sizing: content-box
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden
}
.CodeMirror-cursor {
position: absolute;
pointer-events: none
}
.CodeMirror-measure pre {
position: static
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3
}
div.CodeMirror-dragcursors {
visibility: visible
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible
}
.CodeMirror-selected {
background: #d9d9d9
}
.CodeMirror-focused .CodeMirror-selected {
background: #d7d4f0
}
.CodeMirror-crosshair {
cursor: crosshair
}
.CodeMirror-line::selection,
.CodeMirror-line>span::selection,
.CodeMirror-line>span>span::selection {
background: #d7d4f0
}
.CodeMirror-line::-moz-selection,
.CodeMirror-line>span::-moz-selection,
.CodeMirror-line>span>span::-moz-selection {
background: #d7d4f0
}
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4)
}
.cm-force-border {
padding-right: .1px
}
@media print {
.CodeMirror div.CodeMirror-cursors {
visibility: hidden
}
}
.cm-tab-wrap-hack:after {
content: ''
}
span.CodeMirror-selectedtext {
background: 0 0
}
.EasyMDEContainer {
display: block
}
.CodeMirror-rtl pre {
direction: rtl
}
.EasyMDEContainer.sided--no-fullscreen {
display: flex;
flex-direction: row;
flex-wrap: wrap
}
.EasyMDEContainer .CodeMirror {
box-sizing: border-box;
height: auto;
border: 1px solid #ced4da;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
font: inherit;
z-index: 0;
word-wrap: break-word
}
.EasyMDEContainer .CodeMirror-scroll {
cursor: text
}
.EasyMDEContainer .CodeMirror-fullscreen {
background: #fff;
position: fixed !important;
top: 50px;
left: 0;
right: 0;
bottom: 0;
height: auto;
z-index: 8;
border-right: none !important;
border-bottom-right-radius: 0 !important
}
.EasyMDEContainer .CodeMirror-sided {
width: 50% !important
}
.EasyMDEContainer.sided--no-fullscreen .CodeMirror-sided {
border-right: none !important;
border-bottom-right-radius: 0;
position: relative;
flex: 1 1 auto
}
.EasyMDEContainer .CodeMirror-placeholder {
opacity: .5
}
.EasyMDEContainer .CodeMirror-focused .CodeMirror-selected {
background: #d9d9d9
}
.editor-toolbar {
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
padding: 9px 10px;
border-top: 1px solid #ced4da;
border-left: 1px solid #ced4da;
border-right: 1px solid #ced4da;
border-top-left-radius: 4px;
border-top-right-radius: 4px
}
.editor-toolbar.fullscreen {
width: 100%;
height: 50px;
padding-top: 10px;
padding-bottom: 10px;
box-sizing: border-box;
background: #fff;
border: 0;
position: fixed;
top: 0;
left: 0;
opacity: 1;
z-index: 9
}
.editor-toolbar.fullscreen::before {
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, #fff 0, rgba(255, 255, 255, 0) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0, #fff), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, #fff 0, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, #fff 0, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, #fff 0, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, #fff 0, rgba(255, 255, 255, 0) 100%);
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 0
}
.editor-toolbar.fullscreen::after {
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0, #fff 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0, rgba(255, 255, 255, 0)), color-stop(100%, #fff));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0, #fff 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0, #fff 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0, #fff 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0, #fff 100%);
position: fixed;
top: 0;
right: 0;
margin: 0;
padding: 0
}
.EasyMDEContainer.sided--no-fullscreen .editor-toolbar {
width: 100%
}
.editor-toolbar .easymde-dropdown,
.editor-toolbar button {
background: 0 0;
display: inline-block;
text-align: center;
text-decoration: none !important;
height: 30px;
margin: 0;
padding: 0;
border: 1px solid transparent;
border-radius: 3px;
cursor: pointer
}
.editor-toolbar button {
font-weight: 700;
min-width: 30px;
padding: 0 6px;
white-space: nowrap
}
.editor-toolbar button.active,
.editor-toolbar button:hover {
background: #fcfcfc;
border-color: #95a5a6
}
.editor-toolbar i.separator {
display: inline-block;
width: 0;
border-left: 1px solid #d9d9d9;
border-right: 1px solid #fff;
color: transparent;
text-indent: -10px;
margin: 0 6px
}
.editor-toolbar button:after {
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 65%;
vertical-align: text-bottom;
position: relative;
top: 2px
}
.editor-toolbar button.heading-1:after {
content: "1"
}
.editor-toolbar button.heading-2:after {
content: "2"
}
.editor-toolbar button.heading-3:after {
content: "3"
}
.editor-toolbar button.heading-bigger:after {
content: "▲"
}
.editor-toolbar button.heading-smaller:after {
content: "▼"
}
.editor-toolbar.disabled-for-preview button:not(.no-disable) {
opacity: .6;
pointer-events: none
}
@media only screen and (max-width:700px) {
.editor-toolbar i.no-mobile {
display: none
}
}
.editor-statusbar {
padding: 8px 10px;
font-size: 12px;
color: #959694;
text-align: right
}
.EasyMDEContainer.sided--no-fullscreen .editor-statusbar {
width: 100%
}
.editor-statusbar span {
display: inline-block;
min-width: 4em;
margin-left: 1em
}
.editor-statusbar .lines:before {
content: 'lines: '
}
.editor-statusbar .words:before {
content: 'words: '
}
.editor-statusbar .characters:before {
content: 'characters: '
}
.editor-preview-full {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 7;
overflow: auto;
display: none;
box-sizing: border-box
}
.editor-preview-side {
position: fixed;
bottom: 0;
width: 50%;
top: 50px;
right: 0;
z-index: 9;
overflow: auto;
display: none;
box-sizing: border-box;
border: 1px solid #ddd;
word-wrap: break-word
}
.editor-preview-active-side {
display: block
}
.EasyMDEContainer.sided--no-fullscreen .editor-preview-active-side {
flex: 1 1 auto;
height: auto;
position: static
}
.editor-preview-active {
display: block
}
.editor-preview {
padding: 10px;
background: #fafafa
}
.editor-preview>p {
margin-top: 0
}
.editor-preview pre {
background: #eee;
margin-bottom: 10px
}
.editor-preview table td,
.editor-preview table th {
border: 1px solid #ddd;
padding: 5px
}
.cm-s-easymde .cm-tag {
color: #63a35c
}
.cm-s-easymde .cm-attribute {
color: #795da3
}
.cm-s-easymde .cm-string {
color: #183691
}
.cm-s-easymde .cm-header-1 {
font-size: calc(1.375rem + 1.5vw)
}
.cm-s-easymde .cm-header-2 {
font-size: calc(1.325rem + .9vw)
}
.cm-s-easymde .cm-header-3 {
font-size: calc(1.3rem + .6vw)
}
.cm-s-easymde .cm-header-4 {
font-size: calc(1.275rem + .3vw)
}
.cm-s-easymde .cm-header-5 {
font-size: 1.25rem
}
.cm-s-easymde .cm-header-6 {
font-size: 1rem
}
.cm-s-easymde .cm-header-1,
.cm-s-easymde .cm-header-2,
.cm-s-easymde .cm-header-3,
.cm-s-easymde .cm-header-4,
.cm-s-easymde .cm-header-5,
.cm-s-easymde .cm-header-6 {
margin-bottom: .5rem;
line-height: 1.2
}
.cm-s-easymde .cm-comment {
background: rgba(0, 0, 0, .05);
border-radius: 2px
}
.cm-s-easymde .cm-link {
color: #7f8c8d
}
.cm-s-easymde .cm-url {
color: #aab2b3
}
.cm-s-easymde .cm-quote {
color: #7f8c8d;
font-style: italic
}
.editor-toolbar .easymde-dropdown {
position: relative;
background: linear-gradient(to bottom right, #fff 0, #fff 84%, #333 50%, #333 100%);
border-radius: 0;
border: 1px solid #fff
}
.editor-toolbar .easymde-dropdown:hover {
background: linear-gradient(to bottom right, #fff 0, #fff 84%, #333 50%, #333 100%)
}
.easymde-dropdown-content {
display: block;
visibility: hidden;
position: absolute;
background-color: #f9f9f9;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, .2);
padding: 8px;
z-index: 2;
top: 30px
}
.easymde-dropdown:active .easymde-dropdown-content,
.easymde-dropdown:focus .easymde-dropdown-content,
.easymde-dropdown:focus-within .easymde-dropdown-content {
visibility: visible
}
.easymde-dropdown-content button {
display: block
}
span[data-img-src]::after {
content: '';
background-image: var(--bg-image);
display: block;
max-height: 100%;
max-width: 100%;
background-size: contain;
height: 0;
padding-top: var(--height);
width: var(--width);
background-repeat: no-repeat
}
.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word) {
background: rgba(255, 0, 0, .15)
}
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
{
"autosave": "Gem automatisk",
"content-here-supports-markdown-and-html-code": "Indholdet her understøtter både Markdown og HTML kode",
"plugin-data": {
"description": "Markdown editor, med let brugergrænseflade, til oprettelse af indhold i markdown format.",
"name": "EasyMDE"
},
"spell-checker": "Stavekontrol",
"tab-size": "Fanestørrelse",
"toolbar": "Værktøjslinje"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "EasyMDE",
"description": "Einfacher Editor auf der Grundlage der Auszeichnungssprache Markdown."
},
"toolbar": "Werkzeugleiste",
"tab-size": "Abstände der Tabstopps",
"autosave": "Automatische Speicherung",
"spell-checker": "Rechtschreibprüfung",
"content-here-supports-markdown-and-html-code": "Hier kann der Inhalt eingefügt werden. Der Editor unterstützt Markdown und HTML-Code."
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "EasyMDE",
"description": "Einfacher Editor auf der Grundlage der Auszeichnungssprache Markdown."
},
"toolbar": "Werkzeugleiste",
"tab-size": "Abstände der Tabstopps",
"autosave": "Automatische Speicherung",
"spell-checker": "Rechtschreibprüfung",
"content-here-supports-markdown-and-html-code": "Hier kann der Inhalt eingefügt werden. Der Editor unterstützt Markdown und HTML-Code."
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "EasyMDE",
"description": "Markdown editor, cleaned interface to create markup language."
},
"toolbar": "Toolbar",
"tab-size": "Tab size",
"autosave": "Autosave",
"spell-checker": "Spell Checker",
"content-here-supports-markdown-and-html-code": "Content here supports Markdown and HTML code"
}
+11
View File
@@ -0,0 +1,11 @@
{
"plugin-data": {
"name": "EasyMDE",
"description": "Editor Markdown, interfaz limpia para crear lenguaje de marcado."
},
"toolbar": "Barra de herramientas",
"tab-size": "Tamaño de la tabulación",
"autosave": "Autoguardado",
"content-here-supports-markdown-and-html-code": "Content here supports Markdown and HTML code",
"spell-checker": "Corrector ortográfico"
}
+12
View File
@@ -0,0 +1,12 @@
{
"plugin-data":
{
"name": "EasyMDE",
"description": "ویرایشگر Markdown، رابط ساده برای ایجاد زبان markup."
},
"toolbar": "نوار ابزار",
"tab-size": "اندازه زبانه",
"autosave": "ذخیره خودکار",
"spell-checker": "غلط گیر",
"content-here-supports-markdown-and-html-code": "محتوای اینجا از Markdown و کد HTML پشتیبانی می کند"
}

Some files were not shown because too many files have changed in this diff Show More