Add latest changes from icehrm pro
This commit is contained in:
@@ -13,6 +13,8 @@
|
|||||||
"d3-timeline": "^0.0.5",
|
"d3-timeline": "^0.0.5",
|
||||||
"vis": "^4.21.0",
|
"vis": "^4.21.0",
|
||||||
"handlebars": "^4.0.11",
|
"handlebars": "^4.0.11",
|
||||||
"material-design-icons": "^3.0.1"
|
"material-design-icons": "^3.0.1",
|
||||||
|
"inputmask": "~3.3.11",
|
||||||
|
"flag-icon-css": "~3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
depends="clean"
|
depends="clean"
|
||||||
description="Prepare for build">
|
description="Prepare for build">
|
||||||
<mkdir dir="${basedir}/build/api"/>
|
<mkdir dir="${basedir}/build/api"/>
|
||||||
<mkdir dir="${basedir}/build/api"/>
|
|
||||||
<mkdir dir="${basedir}/build/coverage"/>
|
<mkdir dir="${basedir}/build/coverage"/>
|
||||||
<mkdir dir="${basedir}/build/logs"/>
|
<mkdir dir="${basedir}/build/logs"/>
|
||||||
<mkdir dir="${basedir}/build/pdepend"/>
|
<mkdir dir="${basedir}/build/pdepend"/>
|
||||||
@@ -81,7 +80,7 @@
|
|||||||
<exec executable="${toolsdir}phploc">
|
<exec executable="${toolsdir}phploc">
|
||||||
<arg value="--count-tests" />
|
<arg value="--count-tests" />
|
||||||
<arg path="${basedir}/core/src" />
|
<arg path="${basedir}/core/src" />
|
||||||
<arg path="${basedir}/tests" />
|
<arg path="${basedir}/test" />
|
||||||
</exec>
|
</exec>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
@@ -95,7 +94,7 @@
|
|||||||
<arg value="--log-xml" />
|
<arg value="--log-xml" />
|
||||||
<arg path="${basedir}/build/logs/phploc.xml" />
|
<arg path="${basedir}/build/logs/phploc.xml" />
|
||||||
<arg path="${basedir}/core/src" />
|
<arg path="${basedir}/core/src" />
|
||||||
<arg path="${basedir}/tests" />
|
<arg path="${basedir}/test" />
|
||||||
</exec>
|
</exec>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
<div class="col-xs-12" style="font-size:18px;border-bottom: 1px solid #DDD;margin-bottom: 10px;padding-bottom: 10px;">
|
<div class="col-xs-12" style="font-size:18px;border-bottom: 1px solid #DDD;margin-bottom: 10px;padding-bottom: 10px;">
|
||||||
<button id="employeeProfileEditInfo" class="btn btn-small btn-success" onclick="modJs.edit(_id_);" style="margin-right:10px;"><i class="fa fa-edit"></i> Edit Info</button>
|
<button id="employeeProfileEditInfo" class="btn btn-small btn-success" onclick="modJs.edit(_id_);" style="margin-right:10px;"><i class="fa fa-edit"></i> <t>Edit Info</t></button>
|
||||||
<button id="employeeUploadProfileImage" onclick="showUploadDialog('profile_image__id_','Upload Profile Image','profile_image',_id_,'profile_image__id_','src','url','image');return false;" class="btn btn-small btn-primary" type="button" style="margin-right:10px;"><i class="fa fa-upload"></i> Upload Profile Image</button>
|
<button id="employeeUploadProfileImage" onclick="showUploadDialog('profile_image__id_','Upload Profile Image','profile_image',_id_,'profile_image__id_','src','url','image');return false;" class="btn btn-small btn-primary" type="button" style="margin-right:10px;"><i class="fa fa-upload"></i> <t>Upload Profile Image</t></button>
|
||||||
<button id="employeeDeleteProfileImage" onclick="modJs.deleteProfileImage(_id_);return false;" class="btn btn-small btn-warning" type="button" style="margin-right:10px;"><i class="fa fa-times"></i> Delete Profile Image</button>
|
<button id="employeeDeleteProfileImage" onclick="modJs.deleteProfileImage(_id_);return false;" class="btn btn-small btn-warning" type="button" style="margin-right:10px;"><i class="fa fa-times"></i> <t>Delete Profile Image</t></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -46,17 +46,17 @@
|
|||||||
|
|
||||||
|
|
||||||
<ul class="nav nav-tabs" id="subModTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">
|
<ul class="nav nav-tabs" id="subModTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">
|
||||||
<li class="active"><a id="tabBasic" href="#tabPageBasic">Basic Information</a></li>
|
<li class="active"><a id="tabBasic" href="#tabPageBasic"><t>Basic Information</t></a></li>
|
||||||
<li class=""><a id="tabQualifications" href="#tabPageQualifications">Qualifications</a></li>
|
<li class=""><a id="tabQualifications" href="#tabPageQualifications"><t>Qualifications</t></a></li>
|
||||||
<li class=""><a id="tabFamily" href="#tabPageFamily">Family</a></li>
|
<li class=""><a id="tabFamily" href="#tabPageFamily"><t>Family</t></a></li>
|
||||||
<li class=""><a id="tabDocuments" href="#tabPageDocuments">Documents</a></li>
|
<li class=""><a id="tabDocuments" href="#tabPageDocuments"><t>Documents</t></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane sub-tab active" id="tabPageBasic">
|
<div class="tab-pane sub-tab active" id="tabPageBasic">
|
||||||
<div class="row" style="margin-left:10px;margin-top:20px;">
|
<div class="row" style="margin-left:10px;margin-top:20px;">
|
||||||
<div class="panel panel-default" style="width:97.5%;">
|
<div class="panel panel-default" style="width:97.5%;">
|
||||||
<div class="panel-heading"><h4>Personal Information</h4></div>
|
<div class="panel-heading"><h4><t>Personal Information</t></h4></div>
|
||||||
<div class="panel-body" id="cont_personal_information">
|
<div class="panel-body" id="cont_personal_information">
|
||||||
<div class="col-xs-6 col-md-3" style="font-size:16px;">
|
<div class="col-xs-6 col-md-3" style="font-size:16px;">
|
||||||
<label class="control-label col-xs-12" style="font-size:13px;">#_label_driving_license_#</label>
|
<label class="control-label col-xs-12" style="font-size:13px;">#_label_driving_license_#</label>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
<div class="row" style="margin-left:10px;margin-top:20px;">
|
<div class="row" style="margin-left:10px;margin-top:20px;">
|
||||||
<div class="panel panel-default" style="width:97.5%;">
|
<div class="panel panel-default" style="width:97.5%;">
|
||||||
<div class="panel-heading"><h4>Contact Information</h4></div>
|
<div class="panel-heading"><h4><t>Contact Information</t></h4></div>
|
||||||
<div class="panel-body" id="cont_contact_information">
|
<div class="panel-body" id="cont_contact_information">
|
||||||
<div class="col-xs-6 col-md-3" style="font-size:16px;">
|
<div class="col-xs-6 col-md-3" style="font-size:16px;">
|
||||||
<label class="control-label col-xs-12" style="font-size:13px;">#_label_address1_#</label>
|
<label class="control-label col-xs-12" style="font-size:13px;">#_label_address1_#</label>
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
|
|
||||||
<div class="row" style="margin-left:10px;margin-top:20px;">
|
<div class="row" style="margin-left:10px;margin-top:20px;">
|
||||||
<div class="panel panel-default" style="width:97.5%;">
|
<div class="panel panel-default" style="width:97.5%;">
|
||||||
<div class="panel-heading"><h4>Job Details</h4></div>
|
<div class="panel-heading"><h4><t>Job Details</t></h4></div>
|
||||||
<div class="panel-body" id="cont_job_details">
|
<div class="panel-body" id="cont_job_details">
|
||||||
<div class="col-xs-6 col-md-3" style="font-size:16px;">
|
<div class="col-xs-6 col-md-3" style="font-size:16px;">
|
||||||
<label class="control-label col-xs-12" style="font-size:13px;">#_label_job_title_#</label>
|
<label class="control-label col-xs-12" style="font-size:13px;">#_label_job_title_#</label>
|
||||||
@@ -170,7 +170,7 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><li class="fa fa-times"/></button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><li class="fa fa-times"/></button>
|
||||||
<h3 style="font-size: 17px;">Change User Password</h3>
|
<h3 style="font-size: 17px;"><t>Change Password</t></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form id="adminUsersChangePwd">
|
<form id="adminUsersChangePwd">
|
||||||
@@ -180,14 +180,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group" id="field_newpwd">
|
<div class="control-group" id="field_newpwd">
|
||||||
<label class="control-label" for="newpwd">New Password</label>
|
<label class="control-label" for="newpwd"><t>New Password</t></label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input class="" type="password" id="newpwd" name="newpwd" value="" class="form-control"/>
|
<input class="" type="password" id="newpwd" name="newpwd" value="" class="form-control"/>
|
||||||
<span class="help-inline" id="help_newpwd"></span>
|
<span class="help-inline" id="help_newpwd"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group" id="field_conpwd">
|
<div class="control-group" id="field_conpwd">
|
||||||
<label class="control-label" for="conpwd">Confirm Password</label>
|
<label class="control-label" for="conpwd"><t>Confirm Password</t></label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input class="" type="password" id="conpwd" name="conpwd" value="" class="form-control"/>
|
<input class="" type="password" id="conpwd" name="conpwd" value="" class="form-control"/>
|
||||||
<span class="help-inline" id="help_conpwd"></span>
|
<span class="help-inline" id="help_conpwd"></span>
|
||||||
@@ -196,8 +196,8 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-primary" onclick="modJs.changePasswordConfirm();">Change Password</button>
|
<button class="btn btn-primary" onclick="modJs.changePasswordConfirm();"><t>Change Password</t></button>
|
||||||
<button class="btn" onclick="modJs.closeChangePassword();">Not Now</button>
|
<button class="btn" onclick="modJs.closeChangePassword();"><t>Not Now</t></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -250,4 +250,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div><!-- End tabPageQualifications -->
|
</div><!-- End tabPageQualifications -->
|
||||||
</div>
|
</div>
|
||||||
</div><!-- End tab-content -->
|
</div><!-- End tab-content -->
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"label": "Field Names Setup",
|
"label": "Employee Custom Fields",
|
||||||
"menu": "System",
|
"menu": "Admin",
|
||||||
"order": "7",
|
"order": "83",
|
||||||
"icon": "fa-sort-alpha-asc",
|
"icon": "fa-sliders",
|
||||||
"user_levels": [
|
"user_levels": [
|
||||||
"Admin"
|
"Admin"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -26,10 +26,16 @@ define('MODULE_PATH',dirname(__FILE__));
|
|||||||
include APP_BASE_PATH.'header.php';
|
include APP_BASE_PATH.'header.php';
|
||||||
include APP_BASE_PATH.'modulejslibs.inc.php';
|
include APP_BASE_PATH.'modulejslibs.inc.php';
|
||||||
|
|
||||||
$options = array();
|
$customFields = \Classes\BaseService::getInstance()->getCustomFields("EmployeeTravelRecord");
|
||||||
$options['setRemoteTable'] = 'true';
|
|
||||||
|
$travelRequestOptions = [];
|
||||||
|
$travelRequestOptions['setRemoteTable'] = 'true';
|
||||||
|
$travelRequestOptions['setCustomFields'] = json_encode($customFields);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$moduleBuilder = new \Classes\ModuleBuilder\ModuleBuilder();
|
$moduleBuilder = new \Classes\ModuleBuilder\ModuleBuilder();
|
||||||
|
|
||||||
$moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
|
$moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
|
||||||
'EmployeeTravelRecord',
|
'EmployeeTravelRecord',
|
||||||
'EmployeeTravelRecord',
|
'EmployeeTravelRecord',
|
||||||
@@ -38,8 +44,26 @@ $moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
|
|||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
true,
|
true,
|
||||||
$options
|
$travelRequestOptions
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if ($user->user_level === 'Admin') {
|
||||||
|
$travelCustomFieldOptions = [];
|
||||||
|
$travelCustomFieldOptions['setRemoteTable'] = 'true';
|
||||||
|
$travelCustomFieldOptions['setTableType'] = '\'EmployeeTravelRecord\'';
|
||||||
|
|
||||||
|
$moduleBuilder->addModuleOrGroup(new \Classes\ModuleBuilder\ModuleTab(
|
||||||
|
'TravelCustomField',
|
||||||
|
'CustomField',
|
||||||
|
'Custom Fields',
|
||||||
|
'CustomFieldAdapter',
|
||||||
|
'{"type":"EmployeeTravelRecord"}',
|
||||||
|
'',
|
||||||
|
false,
|
||||||
|
$travelCustomFieldOptions
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
echo \Classes\UIManager::getInstance()->renderModule($moduleBuilder);
|
echo \Classes\UIManager::getInstance()->renderModule($moduleBuilder);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ if(!defined('HOME_LINK_OTHERS')){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Version
|
//Version
|
||||||
define('VERSION', '22.0.0.OS');
|
define('VERSION', '23.0.0.OS');
|
||||||
define('CACHE_VALUE', '22.0.0.OS');
|
define('CACHE_VALUE', '23.0.0.OS');
|
||||||
define('VERSION_NUMBER', '2200');
|
define('VERSION_NUMBER', '2300');
|
||||||
define('VERSION_DATE', '28/04/2018');
|
define('VERSION_DATE', '21/05/2018');
|
||||||
|
|
||||||
if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');}
|
if(!defined('CONTACT_EMAIL')){define('CONTACT_EMAIL','icehrm@gamonoid.com');}
|
||||||
if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');}
|
if(!defined('KEY_PREFIX')){define('KEY_PREFIX','IceHrm');}
|
||||||
|
|||||||
@@ -11,3 +11,9 @@ foreach($moduleManagers as $moduleManagerObj){
|
|||||||
$moduleManagerObj->initQuickAccessMenu();
|
$moduleManagerObj->initQuickAccessMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$supportedLanguage = new \Metadata\Common\Model\SupportedLanguage();
|
||||||
|
$supportedLanguages = $supportedLanguage->Find("1 = 1", []);
|
||||||
|
foreach ($supportedLanguages as $supportedLanguage) {
|
||||||
|
\Classes\UIManager::getInstance()->addLanguageMenuItem($supportedLanguage->name);
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ if (!defined('MODULE_NAME')) {
|
|||||||
define('MODULE_NAME', $moduleName);
|
define('MODULE_NAME', $moduleName);
|
||||||
}
|
}
|
||||||
include 'includes.inc.php';
|
include 'includes.inc.php';
|
||||||
|
|
||||||
if(empty($user)){
|
if(empty($user)){
|
||||||
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
|
$actualLink = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
|
||||||
\Utils\SessionUtils::saveSessionObject('loginRedirect',$actual_link);
|
header("Location:".CLIENT_BASE_URL."login.php?next=".\Base64Url\Base64Url::encode($actualLink));
|
||||||
header("Location:".CLIENT_BASE_URL."login.php");
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty($user->default_module)){
|
if(empty($user->default_module)){
|
||||||
@@ -144,6 +145,7 @@ include('configureUIManager.php');
|
|||||||
<link href="<?=BASE_URL?>css/bootstrap-datetimepicker.min.css" rel="stylesheet">
|
<link href="<?=BASE_URL?>css/bootstrap-datetimepicker.min.css" rel="stylesheet">
|
||||||
<link href="<?=BASE_URL?>js/select2/select2.css" rel="stylesheet">
|
<link href="<?=BASE_URL?>js/select2/select2.css" rel="stylesheet">
|
||||||
<link href="<?=BASE_URL?>js/bootstrap-colorpicker-2.1.1/css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
<link href="<?=BASE_URL?>js/bootstrap-colorpicker-2.1.1/css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
||||||
|
<link href="<?=BASE_URL?>bower_components/flag-icon-css/css/flag-icon.min.css" rel="stylesheet">
|
||||||
|
|
||||||
<link href="<?=BASE_URL?>themecss/AdminLTE.css" rel="stylesheet">
|
<link href="<?=BASE_URL?>themecss/AdminLTE.css" rel="stylesheet">
|
||||||
|
|
||||||
@@ -157,6 +159,7 @@ include('configureUIManager.php');
|
|||||||
<script type="text/javascript" src="<?=BASE_URL?>bower_components/tinymce/tinymce.min.js"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>bower_components/tinymce/tinymce.min.js"></script>
|
||||||
<link href="<?=BASE_URL?>bower_components/simplemde/dist/simplemde.min.css" rel="stylesheet">
|
<link href="<?=BASE_URL?>bower_components/simplemde/dist/simplemde.min.css" rel="stylesheet">
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>bower_components/simplemde/dist/simplemde.min.js"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>bower_components/simplemde/dist/simplemde.min.js"></script>
|
||||||
|
<script type="text/javascript" src="<?=BASE_URL?>bower_components/inputmask/dist/min/jquery.inputmask.bundle.min.js"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>js/signature_pad.js"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>js/signature_pad.js"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>js/date.js"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>js/date.js"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>js/json2.js"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>js/json2.js"></script>
|
||||||
@@ -167,6 +170,7 @@ include('configureUIManager.php');
|
|||||||
<script type="text/javascript" src="<?=BASE_URL?>api/FormValidation.js?v=<?=$jsVersion?>"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>api/FormValidation.js?v=<?=$jsVersion?>"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>api/Notifications.js?v=<?=$jsVersion?>"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>api/Notifications.js?v=<?=$jsVersion?>"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>api/TimeUtils.js?v=<?=$jsVersion?>"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>api/TimeUtils.js?v=<?=$jsVersion?>"></script>
|
||||||
|
<script type="text/javascript" src="<?=BASE_URL?>api/ConversationsAdapter.js?v=<?=$jsVersion?>"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>api/AesCrypt.js?v=<?=$jsVersion?>"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>api/AesCrypt.js?v=<?=$jsVersion?>"></script>
|
||||||
<script type="text/javascript" src="<?=BASE_URL?>api/SocialShare.js?v=<?=$jsVersion?>"></script>
|
<script type="text/javascript" src="<?=BASE_URL?>api/SocialShare.js?v=<?=$jsVersion?>"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ if(is_dir(MODULE_PATH.'/customTemplates/')){
|
|||||||
$ams = scandir(MODULE_PATH.'/customTemplates/');
|
$ams = scandir(MODULE_PATH.'/customTemplates/');
|
||||||
foreach($ams as $am){
|
foreach($ams as $am){
|
||||||
if(!is_dir(MODULE_PATH.'/customTemplates/'.$am) && $am != '.' && $am != '..'){
|
if(!is_dir(MODULE_PATH.'/customTemplates/'.$am) && $am != '.' && $am != '..'){
|
||||||
$customTemplates[$am] = file_get_contents(MODULE_PATH.'/customTemplates/'.$am);
|
$customTemplates[$am] = t(file_get_contents(MODULE_PATH.'/customTemplates/'.$am));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
306
core/lang/de.po
306
core/lang/de.po
@@ -1597,3 +1597,309 @@ msgstr "Anwenden"
|
|||||||
|
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Zurück"
|
msgstr "Zurück"
|
||||||
|
|
||||||
|
msgid "Hours in Time Sheets"
|
||||||
|
msgstr "Stunden in Time Sheets"
|
||||||
|
|
||||||
|
msgid "HR form"
|
||||||
|
msgstr "HR-Formular"
|
||||||
|
|
||||||
|
msgid "HR Form Management"
|
||||||
|
msgstr "HR-Formular-Management"
|
||||||
|
|
||||||
|
msgid "Form Name"
|
||||||
|
msgstr "Formularname"
|
||||||
|
|
||||||
|
msgid "Fields"
|
||||||
|
msgstr "Felder"
|
||||||
|
|
||||||
|
msgid "Employee Froms"
|
||||||
|
msgstr "Mitarbeiter Froms"
|
||||||
|
|
||||||
|
msgid "Share Departments"
|
||||||
|
msgstr "Teilen Abteilungen"
|
||||||
|
|
||||||
|
msgid "Share Employees"
|
||||||
|
msgstr "Aktie Mitarbeiter"
|
||||||
|
|
||||||
|
msgid "Data Importers"
|
||||||
|
msgstr "Daten Importeure"
|
||||||
|
|
||||||
|
msgid "Data Import Files"
|
||||||
|
msgstr "Data Import von Dateien"
|
||||||
|
|
||||||
|
msgid "Data Type"
|
||||||
|
msgstr "Datentyp"
|
||||||
|
|
||||||
|
msgid "Columns"
|
||||||
|
msgstr "Säulen"
|
||||||
|
|
||||||
|
msgid "Field Title"
|
||||||
|
msgstr "Feld Titel"
|
||||||
|
|
||||||
|
msgid "Depends On"
|
||||||
|
msgstr "Kommt drauf an"
|
||||||
|
|
||||||
|
msgid "Depends On Field"
|
||||||
|
msgstr "Hängt Auf Feld"
|
||||||
|
|
||||||
|
msgid "is Key Field"
|
||||||
|
msgstr "Schlüsselfeld ist"
|
||||||
|
|
||||||
|
msgid "is ID Field"
|
||||||
|
msgstr "ID-Feld ist"
|
||||||
|
|
||||||
|
msgid "Data Import Definitions"
|
||||||
|
msgstr "Datenimport Definitionen"
|
||||||
|
|
||||||
|
msgid "File to Import"
|
||||||
|
msgstr "Datei zu importieren"
|
||||||
|
|
||||||
|
msgid "Last Export Results"
|
||||||
|
msgstr "Letzte Ergebnisse exportieren"
|
||||||
|
|
||||||
|
msgid "Time and Attendance"
|
||||||
|
msgstr "Zeit und Anwesenheit"
|
||||||
|
|
||||||
|
msgid "Leave Timeline"
|
||||||
|
msgstr "Lassen Sie Timeline"
|
||||||
|
|
||||||
|
msgid "Insights"
|
||||||
|
msgstr "Insights"
|
||||||
|
|
||||||
|
msgid "Api Access"
|
||||||
|
msgstr "api-Zugang"
|
||||||
|
|
||||||
|
msgid "Change User Password"
|
||||||
|
msgstr "Benutzer-Kennwort ändern"
|
||||||
|
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr "Neues Kennwort"
|
||||||
|
|
||||||
|
msgid "Confirm Password"
|
||||||
|
msgstr "Bestätige das Passwort"
|
||||||
|
|
||||||
|
msgid "Change Password"
|
||||||
|
msgstr "Passwort ändern"
|
||||||
|
|
||||||
|
msgid "Not Now"
|
||||||
|
msgstr "Nicht jetzt"
|
||||||
|
|
||||||
|
msgid "Contact Information"
|
||||||
|
msgstr "Kontakt Informationen"
|
||||||
|
|
||||||
|
msgid "Job Details"
|
||||||
|
msgstr "Job Details"
|
||||||
|
|
||||||
|
msgid "Edit Info"
|
||||||
|
msgstr "Bearbeitungs Information"
|
||||||
|
|
||||||
|
msgid "Upload Profile Image"
|
||||||
|
msgstr "Laden Profilbild"
|
||||||
|
|
||||||
|
msgid "Delete Profile Image"
|
||||||
|
msgstr "Löschen Profilbild"
|
||||||
|
|
||||||
|
msgid "Direct Reports"
|
||||||
|
msgstr "Direkte Rückmeldung"
|
||||||
|
|
||||||
|
msgid "Other Details"
|
||||||
|
msgstr "Andere Details"
|
||||||
|
|
||||||
|
msgid "Family"
|
||||||
|
msgstr "Familie"
|
||||||
|
|
||||||
|
msgid "Custom Fields"
|
||||||
|
msgstr "Benutzerdefinierte Felder"
|
||||||
|
|
||||||
|
msgid "Means of Transportation"
|
||||||
|
msgstr "Transportmitteln"
|
||||||
|
|
||||||
|
msgid "Plane"
|
||||||
|
msgstr "Ebene"
|
||||||
|
|
||||||
|
msgid "Rail"
|
||||||
|
msgstr "Schiene"
|
||||||
|
|
||||||
|
msgid "Taxi"
|
||||||
|
msgstr "Taxi"
|
||||||
|
|
||||||
|
msgid "Own Vehicle"
|
||||||
|
msgstr "Eigenes Fahrzeug"
|
||||||
|
|
||||||
|
msgid "Rented Vehicle"
|
||||||
|
msgstr "Mietfahrzeug"
|
||||||
|
|
||||||
|
msgid "Female"
|
||||||
|
msgstr "Weiblich"
|
||||||
|
|
||||||
|
msgid "Male"
|
||||||
|
msgstr "Männlich"
|
||||||
|
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "Aktiv"
|
||||||
|
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "Inaktiv"
|
||||||
|
|
||||||
|
msgid "Draft"
|
||||||
|
msgstr "Entwurf"
|
||||||
|
|
||||||
|
msgid "Not Clocked In"
|
||||||
|
msgstr "Nicht taktet"
|
||||||
|
|
||||||
|
msgid "Clocked In"
|
||||||
|
msgstr "taktet"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "Datei"
|
||||||
|
|
||||||
|
msgid "Active Employee Report"
|
||||||
|
msgstr "Aktive Mitarbeiterbericht"
|
||||||
|
|
||||||
|
msgid "Employee Attendance Report"
|
||||||
|
msgstr "Angestellt-Anwesenheits-Bericht"
|
||||||
|
|
||||||
|
msgid "Employee Details Report"
|
||||||
|
msgstr "Mitarbeiterdetails Bericht"
|
||||||
|
|
||||||
|
msgid "Employee Leave Entitlement"
|
||||||
|
msgstr "Mitarbeiter Urlaubsanspruch"
|
||||||
|
|
||||||
|
msgid "Employee Leaves Report"
|
||||||
|
msgstr "Mitarbeiter Blätter Bericht"
|
||||||
|
|
||||||
|
msgid "Employee Time Entry Report"
|
||||||
|
msgstr "Mitarbeiterzeit Eintrag Bericht"
|
||||||
|
|
||||||
|
msgid "Employee Time Sheet Report"
|
||||||
|
msgstr "Mitarbeiterzeitblatt Bericht"
|
||||||
|
|
||||||
|
msgid "Employee Time Tracking Report"
|
||||||
|
msgstr "Mitarbeiterzeit Tracking Report"
|
||||||
|
|
||||||
|
msgid "Expense Report"
|
||||||
|
msgstr "Spesenabrechnung"
|
||||||
|
|
||||||
|
msgid "New Hires Employee Report"
|
||||||
|
msgstr "Neue Mitarbeiter Mitarbeiterbericht"
|
||||||
|
|
||||||
|
msgid "Overtime Report"
|
||||||
|
msgstr "Überstunden Bericht"
|
||||||
|
|
||||||
|
msgid "Overtime Request Report"
|
||||||
|
msgstr "Überstunden Anforderungsbericht"
|
||||||
|
|
||||||
|
msgid "Overtime Summary Report"
|
||||||
|
msgstr "Überstunden Summary Report"
|
||||||
|
|
||||||
|
msgid "Payroll Meta Data Export"
|
||||||
|
msgstr "Payroll Meta Data Export"
|
||||||
|
|
||||||
|
msgid "Terminated Employee Report"
|
||||||
|
msgstr "Mitarbeiterbericht terminierte"
|
||||||
|
|
||||||
|
msgid "Travel Request Report"
|
||||||
|
msgstr "Reiseantrag Bericht"
|
||||||
|
|
||||||
|
msgid "Attendance Report"
|
||||||
|
msgstr "Teilnahmebericht"
|
||||||
|
|
||||||
|
msgid "Client Project Time Report"
|
||||||
|
msgstr "Kunde Projektzeitbericht"
|
||||||
|
|
||||||
|
msgid "Download Payslips"
|
||||||
|
msgstr "Herunterladen Lohnzettel"
|
||||||
|
|
||||||
|
msgid "Leaves Report"
|
||||||
|
msgstr "Blätter Bericht"
|
||||||
|
|
||||||
|
msgid "Time Entry Report"
|
||||||
|
msgstr "Zeiteintrag Bericht"
|
||||||
|
|
||||||
|
msgid "Time Sheet Report"
|
||||||
|
msgstr "Zeitblatt Bericht"
|
||||||
|
|
||||||
|
msgid "Time Tracking Report"
|
||||||
|
msgstr "Time Tracking Bericht"
|
||||||
|
|
||||||
|
msgid "Data"
|
||||||
|
msgstr "Daten"
|
||||||
|
|
||||||
|
msgid "Processed"
|
||||||
|
msgstr "Verarbeitet"
|
||||||
|
|
||||||
|
msgid "Not Processed"
|
||||||
|
msgstr "Nicht verarbeitet"
|
||||||
|
|
||||||
|
msgid "Elementary Proficiency"
|
||||||
|
msgstr "Grundkenntnisse"
|
||||||
|
|
||||||
|
msgid "Limited Working Proficiency"
|
||||||
|
msgstr "Begrenzte Fließend"
|
||||||
|
|
||||||
|
msgid "Professional Working Proficiency"
|
||||||
|
msgstr "Professionelle Arbeitsleistung"
|
||||||
|
|
||||||
|
msgid "Full Professional Proficiency"
|
||||||
|
msgstr "Vollständiger Beruf Proficiency"
|
||||||
|
|
||||||
|
msgid "Native or Bilingual Proficiency"
|
||||||
|
msgstr "Muttersprache oder Zweisprachig"
|
||||||
|
|
||||||
|
msgid "Pending"
|
||||||
|
msgstr "steht aus"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "Genehmigt"
|
||||||
|
|
||||||
|
msgid "Rejected"
|
||||||
|
msgstr "Abgelehnt"
|
||||||
|
|
||||||
|
msgid "Cancelled"
|
||||||
|
msgstr "Abgebrochen"
|
||||||
|
|
||||||
|
msgid "Continue"
|
||||||
|
msgstr "Fortsetzen"
|
||||||
|
|
||||||
|
msgid "Cancellation Requested"
|
||||||
|
msgstr "Stornierung Gewünscht"
|
||||||
|
|
||||||
|
msgid "Completed"
|
||||||
|
msgstr "Abgeschlossen"
|
||||||
|
|
||||||
|
msgid "Discussions"
|
||||||
|
msgstr "Diskussionen"
|
||||||
|
|
||||||
|
msgid "Load More"
|
||||||
|
msgstr "Mehr laden"
|
||||||
|
|
||||||
|
msgid "Show More"
|
||||||
|
msgstr "Zeig mehr"
|
||||||
|
|
||||||
|
msgid "Show Less"
|
||||||
|
msgstr "Zeige weniger"
|
||||||
|
|
||||||
|
msgid "Publish"
|
||||||
|
msgstr "Veröffentlichen"
|
||||||
|
|
||||||
|
msgid "Announcements"
|
||||||
|
msgstr "Ankündigungen"
|
||||||
|
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "Senden"
|
||||||
|
|
||||||
|
msgid "Display"
|
||||||
|
msgstr "Anzeige"
|
||||||
|
|
||||||
|
msgid "Public"
|
||||||
|
msgstr "Öffentlichkeit"
|
||||||
|
|
||||||
|
msgid "View Announcements"
|
||||||
|
msgstr "Ansicht Ankündigungen"
|
||||||
|
|
||||||
|
msgid "Conversations"
|
||||||
|
msgstr "Gespräche"
|
||||||
|
|
||||||
|
msgid "Start Now"
|
||||||
|
msgstr "Jetzt anfangen"
|
||||||
|
|||||||
306
core/lang/en.po
306
core/lang/en.po
@@ -1597,3 +1597,309 @@ msgstr "Apply"
|
|||||||
|
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Back"
|
msgstr "Back"
|
||||||
|
|
||||||
|
msgid "Hours in Time Sheets"
|
||||||
|
msgstr "Hours in Time Sheets"
|
||||||
|
|
||||||
|
msgid "HR form"
|
||||||
|
msgstr "HR form"
|
||||||
|
|
||||||
|
msgid "HR Form Management"
|
||||||
|
msgstr "HR Form Management"
|
||||||
|
|
||||||
|
msgid "Form Name"
|
||||||
|
msgstr "Form Name"
|
||||||
|
|
||||||
|
msgid "Fields"
|
||||||
|
msgstr "Fields"
|
||||||
|
|
||||||
|
msgid "Employee Froms"
|
||||||
|
msgstr "Employee Froms"
|
||||||
|
|
||||||
|
msgid "Share Departments"
|
||||||
|
msgstr "Share Departments"
|
||||||
|
|
||||||
|
msgid "Share Employees"
|
||||||
|
msgstr "Share Employees"
|
||||||
|
|
||||||
|
msgid "Data Importers"
|
||||||
|
msgstr "Data Importers"
|
||||||
|
|
||||||
|
msgid "Data Import Files"
|
||||||
|
msgstr "Data Import Files"
|
||||||
|
|
||||||
|
msgid "Data Type"
|
||||||
|
msgstr "Data Type"
|
||||||
|
|
||||||
|
msgid "Columns"
|
||||||
|
msgstr "Columns"
|
||||||
|
|
||||||
|
msgid "Field Title"
|
||||||
|
msgstr "Field Title"
|
||||||
|
|
||||||
|
msgid "Depends On"
|
||||||
|
msgstr "Depends On"
|
||||||
|
|
||||||
|
msgid "Depends On Field"
|
||||||
|
msgstr "Depends On Field"
|
||||||
|
|
||||||
|
msgid "is Key Field"
|
||||||
|
msgstr "is Key Field"
|
||||||
|
|
||||||
|
msgid "is ID Field"
|
||||||
|
msgstr "is ID Field"
|
||||||
|
|
||||||
|
msgid "Data Import Definitions"
|
||||||
|
msgstr "Data Import Definitions"
|
||||||
|
|
||||||
|
msgid "File to Import"
|
||||||
|
msgstr "File to Import"
|
||||||
|
|
||||||
|
msgid "Last Export Results"
|
||||||
|
msgstr "Last Export Results"
|
||||||
|
|
||||||
|
msgid "Time and Attendance"
|
||||||
|
msgstr "Time and Attendance"
|
||||||
|
|
||||||
|
msgid "Leave Timeline"
|
||||||
|
msgstr "Leave Timeline"
|
||||||
|
|
||||||
|
msgid "Insights"
|
||||||
|
msgstr "Insights"
|
||||||
|
|
||||||
|
msgid "Api Access"
|
||||||
|
msgstr "Api Access"
|
||||||
|
|
||||||
|
msgid "Change User Password"
|
||||||
|
msgstr "Change User Password"
|
||||||
|
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr "New Password"
|
||||||
|
|
||||||
|
msgid "Confirm Password"
|
||||||
|
msgstr "Confirm Password"
|
||||||
|
|
||||||
|
msgid "Change Password"
|
||||||
|
msgstr "Change Password"
|
||||||
|
|
||||||
|
msgid "Not Now"
|
||||||
|
msgstr "Not Now"
|
||||||
|
|
||||||
|
msgid "Contact Information"
|
||||||
|
msgstr "Contact Information"
|
||||||
|
|
||||||
|
msgid "Job Details"
|
||||||
|
msgstr "Job Details"
|
||||||
|
|
||||||
|
msgid "Edit Info"
|
||||||
|
msgstr "Edit Info"
|
||||||
|
|
||||||
|
msgid "Upload Profile Image"
|
||||||
|
msgstr "Upload Profile Image"
|
||||||
|
|
||||||
|
msgid "Delete Profile Image"
|
||||||
|
msgstr "Delete Profile Image"
|
||||||
|
|
||||||
|
msgid "Direct Reports"
|
||||||
|
msgstr "Direct Reports"
|
||||||
|
|
||||||
|
msgid "Other Details"
|
||||||
|
msgstr "Other Details"
|
||||||
|
|
||||||
|
msgid "Family"
|
||||||
|
msgstr "Family"
|
||||||
|
|
||||||
|
msgid "Custom Fields"
|
||||||
|
msgstr "Custom Fields"
|
||||||
|
|
||||||
|
msgid "Means of Transportation"
|
||||||
|
msgstr "Means of Transportation"
|
||||||
|
|
||||||
|
msgid "Plane"
|
||||||
|
msgstr "Plane"
|
||||||
|
|
||||||
|
msgid "Rail"
|
||||||
|
msgstr "Rail"
|
||||||
|
|
||||||
|
msgid "Taxi"
|
||||||
|
msgstr "Taxi"
|
||||||
|
|
||||||
|
msgid "Own Vehicle"
|
||||||
|
msgstr "Own Vehicle"
|
||||||
|
|
||||||
|
msgid "Rented Vehicle"
|
||||||
|
msgstr "Rented Vehicle"
|
||||||
|
|
||||||
|
msgid "Female"
|
||||||
|
msgstr "Female"
|
||||||
|
|
||||||
|
msgid "Male"
|
||||||
|
msgstr "Male"
|
||||||
|
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "Active"
|
||||||
|
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "Inactive"
|
||||||
|
|
||||||
|
msgid "Draft"
|
||||||
|
msgstr "Draft"
|
||||||
|
|
||||||
|
msgid "Not Clocked In"
|
||||||
|
msgstr "Not Clocked In"
|
||||||
|
|
||||||
|
msgid "Clocked In"
|
||||||
|
msgstr "Clocked In"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "File"
|
||||||
|
|
||||||
|
msgid "Active Employee Report"
|
||||||
|
msgstr "Active Employee Report"
|
||||||
|
|
||||||
|
msgid "Employee Attendance Report"
|
||||||
|
msgstr "Employee Attendance Report"
|
||||||
|
|
||||||
|
msgid "Employee Details Report"
|
||||||
|
msgstr "Employee Details Report"
|
||||||
|
|
||||||
|
msgid "Employee Leave Entitlement"
|
||||||
|
msgstr "Employee Leave Entitlement"
|
||||||
|
|
||||||
|
msgid "Employee Leaves Report"
|
||||||
|
msgstr "Employee Leaves Report"
|
||||||
|
|
||||||
|
msgid "Employee Time Entry Report"
|
||||||
|
msgstr "Employee Time Entry Report"
|
||||||
|
|
||||||
|
msgid "Employee Time Sheet Report"
|
||||||
|
msgstr "Employee Time Sheet Report"
|
||||||
|
|
||||||
|
msgid "Employee Time Tracking Report"
|
||||||
|
msgstr "Employee Time Tracking Report"
|
||||||
|
|
||||||
|
msgid "Expense Report"
|
||||||
|
msgstr "Expense Report"
|
||||||
|
|
||||||
|
msgid "New Hires Employee Report"
|
||||||
|
msgstr "New Hires Employee Report"
|
||||||
|
|
||||||
|
msgid "Overtime Report"
|
||||||
|
msgstr "Overtime Report"
|
||||||
|
|
||||||
|
msgid "Overtime Request Report"
|
||||||
|
msgstr "Overtime Request Report"
|
||||||
|
|
||||||
|
msgid "Overtime Summary Report"
|
||||||
|
msgstr "Overtime Summary Report"
|
||||||
|
|
||||||
|
msgid "Payroll Meta Data Export"
|
||||||
|
msgstr "Payroll Meta Data Export"
|
||||||
|
|
||||||
|
msgid "Terminated Employee Report"
|
||||||
|
msgstr "Terminated Employee Report"
|
||||||
|
|
||||||
|
msgid "Travel Request Report"
|
||||||
|
msgstr "Travel Request Report"
|
||||||
|
|
||||||
|
msgid "Attendance Report"
|
||||||
|
msgstr "Attendance Report"
|
||||||
|
|
||||||
|
msgid "Client Project Time Report"
|
||||||
|
msgstr "Client Project Time Report"
|
||||||
|
|
||||||
|
msgid "Download Payslips"
|
||||||
|
msgstr "Download Payslips"
|
||||||
|
|
||||||
|
msgid "Leaves Report"
|
||||||
|
msgstr "Leaves Report"
|
||||||
|
|
||||||
|
msgid "Time Entry Report"
|
||||||
|
msgstr "Time Entry Report"
|
||||||
|
|
||||||
|
msgid "Time Sheet Report"
|
||||||
|
msgstr "Time Sheet Report"
|
||||||
|
|
||||||
|
msgid "Time Tracking Report"
|
||||||
|
msgstr "Time Tracking Report"
|
||||||
|
|
||||||
|
msgid "Data"
|
||||||
|
msgstr "Data"
|
||||||
|
|
||||||
|
msgid "Processed"
|
||||||
|
msgstr "Processed"
|
||||||
|
|
||||||
|
msgid "Not Processed"
|
||||||
|
msgstr "Not Processed"
|
||||||
|
|
||||||
|
msgid "Elementary Proficiency"
|
||||||
|
msgstr "Elementary Proficiency"
|
||||||
|
|
||||||
|
msgid "Limited Working Proficiency"
|
||||||
|
msgstr "Limited Working Proficiency"
|
||||||
|
|
||||||
|
msgid "Professional Working Proficiency"
|
||||||
|
msgstr "Professional Working Proficiency"
|
||||||
|
|
||||||
|
msgid "Full Professional Proficiency"
|
||||||
|
msgstr "Full Professional Proficiency"
|
||||||
|
|
||||||
|
msgid "Native or Bilingual Proficiency"
|
||||||
|
msgstr "Native or Bilingual Proficiency"
|
||||||
|
|
||||||
|
msgid "Pending"
|
||||||
|
msgstr "Pending"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "Approved"
|
||||||
|
|
||||||
|
msgid "Rejected"
|
||||||
|
msgstr "Rejected"
|
||||||
|
|
||||||
|
msgid "Cancelled"
|
||||||
|
msgstr "Cancelled"
|
||||||
|
|
||||||
|
msgid "Continue"
|
||||||
|
msgstr "Continue"
|
||||||
|
|
||||||
|
msgid "Cancellation Requested"
|
||||||
|
msgstr "Cancellation Requested"
|
||||||
|
|
||||||
|
msgid "Completed"
|
||||||
|
msgstr "Completed"
|
||||||
|
|
||||||
|
msgid "Discussions"
|
||||||
|
msgstr "Discussions"
|
||||||
|
|
||||||
|
msgid "Load More"
|
||||||
|
msgstr "Load More"
|
||||||
|
|
||||||
|
msgid "Show More"
|
||||||
|
msgstr "Show More"
|
||||||
|
|
||||||
|
msgid "Show Less"
|
||||||
|
msgstr "Show Less"
|
||||||
|
|
||||||
|
msgid "Publish"
|
||||||
|
msgstr "Publish"
|
||||||
|
|
||||||
|
msgid "Announcements"
|
||||||
|
msgstr "Announcements"
|
||||||
|
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "Send"
|
||||||
|
|
||||||
|
msgid "Display"
|
||||||
|
msgstr "Display"
|
||||||
|
|
||||||
|
msgid "Public"
|
||||||
|
msgstr "Public"
|
||||||
|
|
||||||
|
msgid "View Announcements"
|
||||||
|
msgstr "View Announcements"
|
||||||
|
|
||||||
|
msgid "Conversations"
|
||||||
|
msgstr "Conversations"
|
||||||
|
|
||||||
|
msgid "Start Now"
|
||||||
|
msgstr "Start Now"
|
||||||
|
|||||||
306
core/lang/es.po
306
core/lang/es.po
@@ -1597,3 +1597,309 @@ msgstr "Aplicar"
|
|||||||
|
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Espalda"
|
msgstr "Espalda"
|
||||||
|
|
||||||
|
msgid "Hours in Time Sheets"
|
||||||
|
msgstr "Horas en hojas de tiempo"
|
||||||
|
|
||||||
|
msgid "HR form"
|
||||||
|
msgstr "forma HR"
|
||||||
|
|
||||||
|
msgid "HR Form Management"
|
||||||
|
msgstr "Gestión de formularios HR"
|
||||||
|
|
||||||
|
msgid "Form Name"
|
||||||
|
msgstr "Nombre del formulario"
|
||||||
|
|
||||||
|
msgid "Fields"
|
||||||
|
msgstr "Campos"
|
||||||
|
|
||||||
|
msgid "Employee Froms"
|
||||||
|
msgstr "empleado froms"
|
||||||
|
|
||||||
|
msgid "Share Departments"
|
||||||
|
msgstr "Departamentos de Acciones"
|
||||||
|
|
||||||
|
msgid "Share Employees"
|
||||||
|
msgstr "Los empleados de Acciones"
|
||||||
|
|
||||||
|
msgid "Data Importers"
|
||||||
|
msgstr "Los importadores de datos"
|
||||||
|
|
||||||
|
msgid "Data Import Files"
|
||||||
|
msgstr "Importar archivos de datos"
|
||||||
|
|
||||||
|
msgid "Data Type"
|
||||||
|
msgstr "Tipo de datos"
|
||||||
|
|
||||||
|
msgid "Columns"
|
||||||
|
msgstr "columnas"
|
||||||
|
|
||||||
|
msgid "Field Title"
|
||||||
|
msgstr "El campo Título"
|
||||||
|
|
||||||
|
msgid "Depends On"
|
||||||
|
msgstr "Depende de"
|
||||||
|
|
||||||
|
msgid "Depends On Field"
|
||||||
|
msgstr "Depende de Campo"
|
||||||
|
|
||||||
|
msgid "is Key Field"
|
||||||
|
msgstr "El campo es la clave"
|
||||||
|
|
||||||
|
msgid "is ID Field"
|
||||||
|
msgstr "es ID Campo"
|
||||||
|
|
||||||
|
msgid "Data Import Definitions"
|
||||||
|
msgstr "Definiciones de los datos de importación"
|
||||||
|
|
||||||
|
msgid "File to Import"
|
||||||
|
msgstr "Archivo para importar"
|
||||||
|
|
||||||
|
msgid "Last Export Results"
|
||||||
|
msgstr "Los últimos resultados de exportación"
|
||||||
|
|
||||||
|
msgid "Time and Attendance"
|
||||||
|
msgstr "Tiempo y asistencia"
|
||||||
|
|
||||||
|
msgid "Leave Timeline"
|
||||||
|
msgstr "Deja Cronología"
|
||||||
|
|
||||||
|
msgid "Insights"
|
||||||
|
msgstr "Insights"
|
||||||
|
|
||||||
|
msgid "Api Access"
|
||||||
|
msgstr "acceso a la API"
|
||||||
|
|
||||||
|
msgid "Change User Password"
|
||||||
|
msgstr "Cambiar contraseña del usuario"
|
||||||
|
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr "Nueva contraseña"
|
||||||
|
|
||||||
|
msgid "Confirm Password"
|
||||||
|
msgstr "Confirmar contraseña"
|
||||||
|
|
||||||
|
msgid "Change Password"
|
||||||
|
msgstr "Cambia la contraseña"
|
||||||
|
|
||||||
|
msgid "Not Now"
|
||||||
|
msgstr "Ahora no"
|
||||||
|
|
||||||
|
msgid "Contact Information"
|
||||||
|
msgstr "Información del contacto"
|
||||||
|
|
||||||
|
msgid "Job Details"
|
||||||
|
msgstr "Detalles del trabajo"
|
||||||
|
|
||||||
|
msgid "Edit Info"
|
||||||
|
msgstr "Editar información"
|
||||||
|
|
||||||
|
msgid "Upload Profile Image"
|
||||||
|
msgstr "Sube Imagen del perfil"
|
||||||
|
|
||||||
|
msgid "Delete Profile Image"
|
||||||
|
msgstr "Eliminar Imagen del perfil"
|
||||||
|
|
||||||
|
msgid "Direct Reports"
|
||||||
|
msgstr "Reportes directos"
|
||||||
|
|
||||||
|
msgid "Other Details"
|
||||||
|
msgstr "Otros detalles"
|
||||||
|
|
||||||
|
msgid "Family"
|
||||||
|
msgstr "Familia"
|
||||||
|
|
||||||
|
msgid "Custom Fields"
|
||||||
|
msgstr "Campos Personalizados"
|
||||||
|
|
||||||
|
msgid "Means of Transportation"
|
||||||
|
msgstr "Medios de transporte"
|
||||||
|
|
||||||
|
msgid "Plane"
|
||||||
|
msgstr "Avión"
|
||||||
|
|
||||||
|
msgid "Rail"
|
||||||
|
msgstr "Carril"
|
||||||
|
|
||||||
|
msgid "Taxi"
|
||||||
|
msgstr "Taxi"
|
||||||
|
|
||||||
|
msgid "Own Vehicle"
|
||||||
|
msgstr "Vehículo propio"
|
||||||
|
|
||||||
|
msgid "Rented Vehicle"
|
||||||
|
msgstr "Vehículo alquilado"
|
||||||
|
|
||||||
|
msgid "Female"
|
||||||
|
msgstr "Hembra"
|
||||||
|
|
||||||
|
msgid "Male"
|
||||||
|
msgstr "Masculino"
|
||||||
|
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "Activo"
|
||||||
|
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "Inactivo"
|
||||||
|
|
||||||
|
msgid "Draft"
|
||||||
|
msgstr "Borrador"
|
||||||
|
|
||||||
|
msgid "Not Clocked In"
|
||||||
|
msgstr "No cronometró"
|
||||||
|
|
||||||
|
msgid "Clocked In"
|
||||||
|
msgstr "En Clocked"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "Archivo"
|
||||||
|
|
||||||
|
msgid "Active Employee Report"
|
||||||
|
msgstr "Informe Empleado Activo"
|
||||||
|
|
||||||
|
msgid "Employee Attendance Report"
|
||||||
|
msgstr "Informe de asistencia a los empleados"
|
||||||
|
|
||||||
|
msgid "Employee Details Report"
|
||||||
|
msgstr "Empleado detalles Notificar"
|
||||||
|
|
||||||
|
msgid "Employee Leave Entitlement"
|
||||||
|
msgstr "Empleado Derecho a vacaciones"
|
||||||
|
|
||||||
|
msgid "Employee Leaves Report"
|
||||||
|
msgstr "Informe Hojas empleado"
|
||||||
|
|
||||||
|
msgid "Employee Time Entry Report"
|
||||||
|
msgstr "Informe de registro de tiempo empleado"
|
||||||
|
|
||||||
|
msgid "Employee Time Sheet Report"
|
||||||
|
msgstr "Hoja de Informe Tiempo empleado"
|
||||||
|
|
||||||
|
msgid "Employee Time Tracking Report"
|
||||||
|
msgstr "Informe de seguimiento de tiempo empleado"
|
||||||
|
|
||||||
|
msgid "Expense Report"
|
||||||
|
msgstr "Informe de gastos"
|
||||||
|
|
||||||
|
msgid "New Hires Employee Report"
|
||||||
|
msgstr "Nuevos empleados Informe del Empleado"
|
||||||
|
|
||||||
|
msgid "Overtime Report"
|
||||||
|
msgstr "Informe de las horas extraordinarias"
|
||||||
|
|
||||||
|
msgid "Overtime Request Report"
|
||||||
|
msgstr "Solicitud de Informe de horas extras"
|
||||||
|
|
||||||
|
msgid "Overtime Summary Report"
|
||||||
|
msgstr "Informe de resumen de horas extras"
|
||||||
|
|
||||||
|
msgid "Payroll Meta Data Export"
|
||||||
|
msgstr "Nómina de Meta Data Export"
|
||||||
|
|
||||||
|
msgid "Terminated Employee Report"
|
||||||
|
msgstr "Terminado Informe del Empleado"
|
||||||
|
|
||||||
|
msgid "Travel Request Report"
|
||||||
|
msgstr "Solicitud de Informe de viaje"
|
||||||
|
|
||||||
|
msgid "Attendance Report"
|
||||||
|
msgstr "Reporte de asistencia"
|
||||||
|
|
||||||
|
msgid "Client Project Time Report"
|
||||||
|
msgstr "Proyecto cliente Hora del informe"
|
||||||
|
|
||||||
|
msgid "Download Payslips"
|
||||||
|
msgstr "Los recibos de pago de descarga"
|
||||||
|
|
||||||
|
msgid "Leaves Report"
|
||||||
|
msgstr "deja el Informe"
|
||||||
|
|
||||||
|
msgid "Time Entry Report"
|
||||||
|
msgstr "Informe Hora entrada"
|
||||||
|
|
||||||
|
msgid "Time Sheet Report"
|
||||||
|
msgstr "Informe de características TIEMPO"
|
||||||
|
|
||||||
|
msgid "Time Tracking Report"
|
||||||
|
msgstr "Informe de seguimiento de tiempo"
|
||||||
|
|
||||||
|
msgid "Data"
|
||||||
|
msgstr "Datos"
|
||||||
|
|
||||||
|
msgid "Processed"
|
||||||
|
msgstr "Procesada"
|
||||||
|
|
||||||
|
msgid "Not Processed"
|
||||||
|
msgstr "No procesado"
|
||||||
|
|
||||||
|
msgid "Elementary Proficiency"
|
||||||
|
msgstr "Competencia básica"
|
||||||
|
|
||||||
|
msgid "Limited Working Proficiency"
|
||||||
|
msgstr "Competencia básica limitada"
|
||||||
|
|
||||||
|
msgid "Professional Working Proficiency"
|
||||||
|
msgstr "Competencia básica profesional"
|
||||||
|
|
||||||
|
msgid "Full Professional Proficiency"
|
||||||
|
msgstr "Competencia profesional completa"
|
||||||
|
|
||||||
|
msgid "Native or Bilingual Proficiency"
|
||||||
|
msgstr "Competencia bilingüe o nativa"
|
||||||
|
|
||||||
|
msgid "Pending"
|
||||||
|
msgstr "Pendiente"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "Aprobado"
|
||||||
|
|
||||||
|
msgid "Rejected"
|
||||||
|
msgstr "Rechazado"
|
||||||
|
|
||||||
|
msgid "Cancelled"
|
||||||
|
msgstr "Cancelado"
|
||||||
|
|
||||||
|
msgid "Continue"
|
||||||
|
msgstr "Continuar"
|
||||||
|
|
||||||
|
msgid "Cancellation Requested"
|
||||||
|
msgstr "cancelación solicitada"
|
||||||
|
|
||||||
|
msgid "Completed"
|
||||||
|
msgstr "Terminado"
|
||||||
|
|
||||||
|
msgid "Discussions"
|
||||||
|
msgstr "discusiones"
|
||||||
|
|
||||||
|
msgid "Load More"
|
||||||
|
msgstr "Carga más"
|
||||||
|
|
||||||
|
msgid "Show More"
|
||||||
|
msgstr "Mostrar más"
|
||||||
|
|
||||||
|
msgid "Show Less"
|
||||||
|
msgstr "Muestra menos"
|
||||||
|
|
||||||
|
msgid "Publish"
|
||||||
|
msgstr "Publicar"
|
||||||
|
|
||||||
|
msgid "Announcements"
|
||||||
|
msgstr "anuncios"
|
||||||
|
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "Enviar"
|
||||||
|
|
||||||
|
msgid "Display"
|
||||||
|
msgstr "Monitor"
|
||||||
|
|
||||||
|
msgid "Public"
|
||||||
|
msgstr "Público"
|
||||||
|
|
||||||
|
msgid "View Announcements"
|
||||||
|
msgstr "Ver los anuncios"
|
||||||
|
|
||||||
|
msgid "Conversations"
|
||||||
|
msgstr "conversaciones"
|
||||||
|
|
||||||
|
msgid "Start Now"
|
||||||
|
msgstr "Empezar ahora"
|
||||||
|
|||||||
306
core/lang/fr.po
306
core/lang/fr.po
@@ -1597,3 +1597,309 @@ msgstr "Appliquer"
|
|||||||
|
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Arrière"
|
msgstr "Arrière"
|
||||||
|
|
||||||
|
msgid "Hours in Time Sheets"
|
||||||
|
msgstr "Heures feuilles de temps"
|
||||||
|
|
||||||
|
msgid "HR form"
|
||||||
|
msgstr "sous forme de ressources humaines"
|
||||||
|
|
||||||
|
msgid "HR Form Management"
|
||||||
|
msgstr "Gestion du formulaire RH"
|
||||||
|
|
||||||
|
msgid "Form Name"
|
||||||
|
msgstr "Nom de forme"
|
||||||
|
|
||||||
|
msgid "Fields"
|
||||||
|
msgstr "Des champs"
|
||||||
|
|
||||||
|
msgid "Employee Froms"
|
||||||
|
msgstr "employé Froms"
|
||||||
|
|
||||||
|
msgid "Share Departments"
|
||||||
|
msgstr "Départements Partager"
|
||||||
|
|
||||||
|
msgid "Share Employees"
|
||||||
|
msgstr "Employés Share"
|
||||||
|
|
||||||
|
msgid "Data Importers"
|
||||||
|
msgstr "Importateurs de données"
|
||||||
|
|
||||||
|
msgid "Data Import Files"
|
||||||
|
msgstr "Importer des fichiers de données"
|
||||||
|
|
||||||
|
msgid "Data Type"
|
||||||
|
msgstr "Type de données"
|
||||||
|
|
||||||
|
msgid "Columns"
|
||||||
|
msgstr "colonnes"
|
||||||
|
|
||||||
|
msgid "Field Title"
|
||||||
|
msgstr "Titre terrain"
|
||||||
|
|
||||||
|
msgid "Depends On"
|
||||||
|
msgstr "Dépend de"
|
||||||
|
|
||||||
|
msgid "Depends On Field"
|
||||||
|
msgstr "Sur le terrain dépend"
|
||||||
|
|
||||||
|
msgid "is Key Field"
|
||||||
|
msgstr "est Key Field"
|
||||||
|
|
||||||
|
msgid "is ID Field"
|
||||||
|
msgstr "est Champ ID"
|
||||||
|
|
||||||
|
msgid "Data Import Definitions"
|
||||||
|
msgstr "Définitions Importer des données"
|
||||||
|
|
||||||
|
msgid "File to Import"
|
||||||
|
msgstr "Fichier à importer"
|
||||||
|
|
||||||
|
msgid "Last Export Results"
|
||||||
|
msgstr "Derniers résultats Export"
|
||||||
|
|
||||||
|
msgid "Time and Attendance"
|
||||||
|
msgstr "Le temps et la fréquentation"
|
||||||
|
|
||||||
|
msgid "Leave Timeline"
|
||||||
|
msgstr "Laissez Timeline"
|
||||||
|
|
||||||
|
msgid "Insights"
|
||||||
|
msgstr "Insights"
|
||||||
|
|
||||||
|
msgid "Api Access"
|
||||||
|
msgstr "Accès api"
|
||||||
|
|
||||||
|
msgid "Change User Password"
|
||||||
|
msgstr "Changer mot de passe de l'utilisateur"
|
||||||
|
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr "nouveau mot de passe"
|
||||||
|
|
||||||
|
msgid "Confirm Password"
|
||||||
|
msgstr "Confirmez le mot de passe"
|
||||||
|
|
||||||
|
msgid "Change Password"
|
||||||
|
msgstr "Changer le mot de passe"
|
||||||
|
|
||||||
|
msgid "Not Now"
|
||||||
|
msgstr "Pas maintenant"
|
||||||
|
|
||||||
|
msgid "Contact Information"
|
||||||
|
msgstr "Informations de contact"
|
||||||
|
|
||||||
|
msgid "Job Details"
|
||||||
|
msgstr "Détails du poste"
|
||||||
|
|
||||||
|
msgid "Edit Info"
|
||||||
|
msgstr "Modifier les informations"
|
||||||
|
|
||||||
|
msgid "Upload Profile Image"
|
||||||
|
msgstr "Ajouter un profil Photo"
|
||||||
|
|
||||||
|
msgid "Delete Profile Image"
|
||||||
|
msgstr "Supprimer le profil image"
|
||||||
|
|
||||||
|
msgid "Direct Reports"
|
||||||
|
msgstr "Rapports directs"
|
||||||
|
|
||||||
|
msgid "Other Details"
|
||||||
|
msgstr "Autres détails"
|
||||||
|
|
||||||
|
msgid "Family"
|
||||||
|
msgstr "Famille"
|
||||||
|
|
||||||
|
msgid "Custom Fields"
|
||||||
|
msgstr "Les champs personnalisés"
|
||||||
|
|
||||||
|
msgid "Means of Transportation"
|
||||||
|
msgstr "Moyens de transport"
|
||||||
|
|
||||||
|
msgid "Plane"
|
||||||
|
msgstr "Avion"
|
||||||
|
|
||||||
|
msgid "Rail"
|
||||||
|
msgstr "Rail"
|
||||||
|
|
||||||
|
msgid "Taxi"
|
||||||
|
msgstr "Taxi"
|
||||||
|
|
||||||
|
msgid "Own Vehicle"
|
||||||
|
msgstr "Propre véhicule"
|
||||||
|
|
||||||
|
msgid "Rented Vehicle"
|
||||||
|
msgstr "véhicule loué"
|
||||||
|
|
||||||
|
msgid "Female"
|
||||||
|
msgstr "Femelle"
|
||||||
|
|
||||||
|
msgid "Male"
|
||||||
|
msgstr "Mâle"
|
||||||
|
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "actif"
|
||||||
|
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "Inactif"
|
||||||
|
|
||||||
|
msgid "Draft"
|
||||||
|
msgstr "Brouillon"
|
||||||
|
|
||||||
|
msgid "Not Clocked In"
|
||||||
|
msgstr "Non cadencées"
|
||||||
|
|
||||||
|
msgid "Clocked In"
|
||||||
|
msgstr "cadencées"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "Fichier"
|
||||||
|
|
||||||
|
msgid "Active Employee Report"
|
||||||
|
msgstr "Rapport actif employé"
|
||||||
|
|
||||||
|
msgid "Employee Attendance Report"
|
||||||
|
msgstr "Rapport de présence des employés"
|
||||||
|
|
||||||
|
msgid "Employee Details Report"
|
||||||
|
msgstr "Rapport de l'employé Détails"
|
||||||
|
|
||||||
|
msgid "Employee Leave Entitlement"
|
||||||
|
msgstr "Employé droit au congé"
|
||||||
|
|
||||||
|
msgid "Employee Leaves Report"
|
||||||
|
msgstr "Rapport feuilles des employés"
|
||||||
|
|
||||||
|
msgid "Employee Time Entry Report"
|
||||||
|
msgstr "Rapport employé à temps d'entrée"
|
||||||
|
|
||||||
|
msgid "Employee Time Sheet Report"
|
||||||
|
msgstr "Rapport de feuille de temps des employés"
|
||||||
|
|
||||||
|
msgid "Employee Time Tracking Report"
|
||||||
|
msgstr "Rapport de suivi du temps des employés"
|
||||||
|
|
||||||
|
msgid "Expense Report"
|
||||||
|
msgstr "Rapport de dépenses"
|
||||||
|
|
||||||
|
msgid "New Hires Employee Report"
|
||||||
|
msgstr "Nouvelles embauches Rapport de l'employé"
|
||||||
|
|
||||||
|
msgid "Overtime Report"
|
||||||
|
msgstr "Rapport des heures supplémentaires"
|
||||||
|
|
||||||
|
msgid "Overtime Request Report"
|
||||||
|
msgstr "Rapport des heures supplémentaires de demande"
|
||||||
|
|
||||||
|
msgid "Overtime Summary Report"
|
||||||
|
msgstr "Rapport sommaire des heures supplémentaires"
|
||||||
|
|
||||||
|
msgid "Payroll Meta Data Export"
|
||||||
|
msgstr "Paie Meta Exporter les données"
|
||||||
|
|
||||||
|
msgid "Terminated Employee Report"
|
||||||
|
msgstr "Rapport de l'employé Terminated"
|
||||||
|
|
||||||
|
msgid "Travel Request Report"
|
||||||
|
msgstr "Rapport Demande de Voyage"
|
||||||
|
|
||||||
|
msgid "Attendance Report"
|
||||||
|
msgstr "Rapport de présence"
|
||||||
|
|
||||||
|
msgid "Client Project Time Report"
|
||||||
|
msgstr "Rapport sur le projet Client Temps"
|
||||||
|
|
||||||
|
msgid "Download Payslips"
|
||||||
|
msgstr "Télécharger fiches de paie"
|
||||||
|
|
||||||
|
msgid "Leaves Report"
|
||||||
|
msgstr "Rapport laisse"
|
||||||
|
|
||||||
|
msgid "Time Entry Report"
|
||||||
|
msgstr "Rapport du temps d'entrée"
|
||||||
|
|
||||||
|
msgid "Time Sheet Report"
|
||||||
|
msgstr "Rapport de feuille de temps"
|
||||||
|
|
||||||
|
msgid "Time Tracking Report"
|
||||||
|
msgstr "Rapport de suivi du temps"
|
||||||
|
|
||||||
|
msgid "Data"
|
||||||
|
msgstr "Les données"
|
||||||
|
|
||||||
|
msgid "Processed"
|
||||||
|
msgstr "Traité"
|
||||||
|
|
||||||
|
msgid "Not Processed"
|
||||||
|
msgstr "Non traité"
|
||||||
|
|
||||||
|
msgid "Elementary Proficiency"
|
||||||
|
msgstr "Notions"
|
||||||
|
|
||||||
|
msgid "Limited Working Proficiency"
|
||||||
|
msgstr "Compétence professionnelle limitée"
|
||||||
|
|
||||||
|
msgid "Professional Working Proficiency"
|
||||||
|
msgstr "Compétence professionnelle"
|
||||||
|
|
||||||
|
msgid "Full Professional Proficiency"
|
||||||
|
msgstr "Capacité professionnelle complète"
|
||||||
|
|
||||||
|
msgid "Native or Bilingual Proficiency"
|
||||||
|
msgstr "Bilingue ou langue natale"
|
||||||
|
|
||||||
|
msgid "Pending"
|
||||||
|
msgstr "en attendant"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "Approuvé"
|
||||||
|
|
||||||
|
msgid "Rejected"
|
||||||
|
msgstr "Rejeté"
|
||||||
|
|
||||||
|
msgid "Cancelled"
|
||||||
|
msgstr "Annulé"
|
||||||
|
|
||||||
|
msgid "Continue"
|
||||||
|
msgstr "Continuer"
|
||||||
|
|
||||||
|
msgid "Cancellation Requested"
|
||||||
|
msgstr "Annulation demandée"
|
||||||
|
|
||||||
|
msgid "Completed"
|
||||||
|
msgstr "Terminé"
|
||||||
|
|
||||||
|
msgid "Discussions"
|
||||||
|
msgstr "discussions"
|
||||||
|
|
||||||
|
msgid "Load More"
|
||||||
|
msgstr "Charger plus"
|
||||||
|
|
||||||
|
msgid "Show More"
|
||||||
|
msgstr "Montre plus"
|
||||||
|
|
||||||
|
msgid "Show Less"
|
||||||
|
msgstr "Montre moins"
|
||||||
|
|
||||||
|
msgid "Publish"
|
||||||
|
msgstr "Publier"
|
||||||
|
|
||||||
|
msgid "Announcements"
|
||||||
|
msgstr "Annonces"
|
||||||
|
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "Envoyer"
|
||||||
|
|
||||||
|
msgid "Display"
|
||||||
|
msgstr "Afficher"
|
||||||
|
|
||||||
|
msgid "Public"
|
||||||
|
msgstr "Publique"
|
||||||
|
|
||||||
|
msgid "View Announcements"
|
||||||
|
msgstr "Afficher les annonces"
|
||||||
|
|
||||||
|
msgid "Conversations"
|
||||||
|
msgstr "conversations"
|
||||||
|
|
||||||
|
msgid "Start Now"
|
||||||
|
msgstr "Commencez maintenant"
|
||||||
|
|||||||
1142
core/lang/it.po
1142
core/lang/it.po
File diff suppressed because it is too large
Load Diff
306
core/lang/ja.po
306
core/lang/ja.po
@@ -1597,3 +1597,309 @@ msgstr "適用します"
|
|||||||
|
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "バック"
|
msgstr "バック"
|
||||||
|
|
||||||
|
msgid "Hours in Time Sheets"
|
||||||
|
msgstr "タイムシートで時間"
|
||||||
|
|
||||||
|
msgid "HR form"
|
||||||
|
msgstr "HRフォーム"
|
||||||
|
|
||||||
|
msgid "HR Form Management"
|
||||||
|
msgstr "HRフォームの管理"
|
||||||
|
|
||||||
|
msgid "Form Name"
|
||||||
|
msgstr "フォーム名"
|
||||||
|
|
||||||
|
msgid "Fields"
|
||||||
|
msgstr "フィールド"
|
||||||
|
|
||||||
|
msgid "Employee Froms"
|
||||||
|
msgstr "従業員はFroms"
|
||||||
|
|
||||||
|
msgid "Share Departments"
|
||||||
|
msgstr "株式部門"
|
||||||
|
|
||||||
|
msgid "Share Employees"
|
||||||
|
msgstr "共有従業員"
|
||||||
|
|
||||||
|
msgid "Data Importers"
|
||||||
|
msgstr "データ輸入"
|
||||||
|
|
||||||
|
msgid "Data Import Files"
|
||||||
|
msgstr "データのインポートファイル"
|
||||||
|
|
||||||
|
msgid "Data Type"
|
||||||
|
msgstr "データ・タイプ"
|
||||||
|
|
||||||
|
msgid "Columns"
|
||||||
|
msgstr "コラム"
|
||||||
|
|
||||||
|
msgid "Field Title"
|
||||||
|
msgstr "フィールドのタイトル"
|
||||||
|
|
||||||
|
msgid "Depends On"
|
||||||
|
msgstr "依存"
|
||||||
|
|
||||||
|
msgid "Depends On Field"
|
||||||
|
msgstr "フィールドに依存します"
|
||||||
|
|
||||||
|
msgid "is Key Field"
|
||||||
|
msgstr "キー・フィールドであります"
|
||||||
|
|
||||||
|
msgid "is ID Field"
|
||||||
|
msgstr "IDフィールドは、"
|
||||||
|
|
||||||
|
msgid "Data Import Definitions"
|
||||||
|
msgstr "データのインポートの定義"
|
||||||
|
|
||||||
|
msgid "File to Import"
|
||||||
|
msgstr "インポートするファイル"
|
||||||
|
|
||||||
|
msgid "Last Export Results"
|
||||||
|
msgstr "最終結果のエクスポート"
|
||||||
|
|
||||||
|
msgid "Time and Attendance"
|
||||||
|
msgstr "時間と出席"
|
||||||
|
|
||||||
|
msgid "Leave Timeline"
|
||||||
|
msgstr "タイムラインを残します"
|
||||||
|
|
||||||
|
msgid "Insights"
|
||||||
|
msgstr "洞察"
|
||||||
|
|
||||||
|
msgid "Api Access"
|
||||||
|
msgstr "APIアクセス"
|
||||||
|
|
||||||
|
msgid "Change User Password"
|
||||||
|
msgstr "ユーザパスワードの変更"
|
||||||
|
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr "新しいパスワード"
|
||||||
|
|
||||||
|
msgid "Confirm Password"
|
||||||
|
msgstr "パスワードを認証する"
|
||||||
|
|
||||||
|
msgid "Change Password"
|
||||||
|
msgstr "パスワードを変更する"
|
||||||
|
|
||||||
|
msgid "Not Now"
|
||||||
|
msgstr "今はやめろ"
|
||||||
|
|
||||||
|
msgid "Contact Information"
|
||||||
|
msgstr "連絡先"
|
||||||
|
|
||||||
|
msgid "Job Details"
|
||||||
|
msgstr "仕事の詳細"
|
||||||
|
|
||||||
|
msgid "Edit Info"
|
||||||
|
msgstr "編集情報"
|
||||||
|
|
||||||
|
msgid "Upload Profile Image"
|
||||||
|
msgstr "プロフィール画像をアップロード"
|
||||||
|
|
||||||
|
msgid "Delete Profile Image"
|
||||||
|
msgstr "プロフィール画像を削除します"
|
||||||
|
|
||||||
|
msgid "Direct Reports"
|
||||||
|
msgstr "直接レポート"
|
||||||
|
|
||||||
|
msgid "Other Details"
|
||||||
|
msgstr "その他の情報"
|
||||||
|
|
||||||
|
msgid "Family"
|
||||||
|
msgstr "家族"
|
||||||
|
|
||||||
|
msgid "Custom Fields"
|
||||||
|
msgstr "カスタムフィールド"
|
||||||
|
|
||||||
|
msgid "Means of Transportation"
|
||||||
|
msgstr "翻訳の意味"
|
||||||
|
|
||||||
|
msgid "Plane"
|
||||||
|
msgstr "飛行機"
|
||||||
|
|
||||||
|
msgid "Rail"
|
||||||
|
msgstr "レール"
|
||||||
|
|
||||||
|
msgid "Taxi"
|
||||||
|
msgstr "タクシー"
|
||||||
|
|
||||||
|
msgid "Own Vehicle"
|
||||||
|
msgstr "自車"
|
||||||
|
|
||||||
|
msgid "Rented Vehicle"
|
||||||
|
msgstr "レンタル車"
|
||||||
|
|
||||||
|
msgid "Female"
|
||||||
|
msgstr "女性"
|
||||||
|
|
||||||
|
msgid "Male"
|
||||||
|
msgstr "男性"
|
||||||
|
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "アクティブ"
|
||||||
|
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "不活発"
|
||||||
|
|
||||||
|
msgid "Draft"
|
||||||
|
msgstr "ドラフト"
|
||||||
|
|
||||||
|
msgid "Not Clocked In"
|
||||||
|
msgstr "クロックインではありません"
|
||||||
|
|
||||||
|
msgid "Clocked In"
|
||||||
|
msgstr "クロックイン"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "ファイル"
|
||||||
|
|
||||||
|
msgid "Active Employee Report"
|
||||||
|
msgstr "アクティブな従業員レポート"
|
||||||
|
|
||||||
|
msgid "Employee Attendance Report"
|
||||||
|
msgstr "従業員の出席レポート"
|
||||||
|
|
||||||
|
msgid "Employee Details Report"
|
||||||
|
msgstr "従業員詳細レポート"
|
||||||
|
|
||||||
|
msgid "Employee Leave Entitlement"
|
||||||
|
msgstr "従業員の休暇資格"
|
||||||
|
|
||||||
|
msgid "Employee Leaves Report"
|
||||||
|
msgstr "従業員の葉レポート"
|
||||||
|
|
||||||
|
msgid "Employee Time Entry Report"
|
||||||
|
msgstr "従業員のタイムエントリレポート"
|
||||||
|
|
||||||
|
msgid "Employee Time Sheet Report"
|
||||||
|
msgstr "従業員のタイムシートレポート"
|
||||||
|
|
||||||
|
msgid "Employee Time Tracking Report"
|
||||||
|
msgstr "従業員のタイムトラッキングレポート"
|
||||||
|
|
||||||
|
msgid "Expense Report"
|
||||||
|
msgstr "経費報告書"
|
||||||
|
|
||||||
|
msgid "New Hires Employee Report"
|
||||||
|
msgstr "新入社員従業員レポート"
|
||||||
|
|
||||||
|
msgid "Overtime Report"
|
||||||
|
msgstr "残業レポート"
|
||||||
|
|
||||||
|
msgid "Overtime Request Report"
|
||||||
|
msgstr "残業リクエストレポート"
|
||||||
|
|
||||||
|
msgid "Overtime Summary Report"
|
||||||
|
msgstr "残業の概要レポート"
|
||||||
|
|
||||||
|
msgid "Payroll Meta Data Export"
|
||||||
|
msgstr "給与メタデータのエクスポート"
|
||||||
|
|
||||||
|
msgid "Terminated Employee Report"
|
||||||
|
msgstr "退職した従業員レポート"
|
||||||
|
|
||||||
|
msgid "Travel Request Report"
|
||||||
|
msgstr "トラベルリクエストレポート"
|
||||||
|
|
||||||
|
msgid "Attendance Report"
|
||||||
|
msgstr "出席報告書"
|
||||||
|
|
||||||
|
msgid "Client Project Time Report"
|
||||||
|
msgstr "クライアントのプロジェクト時間レポート"
|
||||||
|
|
||||||
|
msgid "Download Payslips"
|
||||||
|
msgstr "ダウンロード給与明細"
|
||||||
|
|
||||||
|
msgid "Leaves Report"
|
||||||
|
msgstr "報告書は、葉"
|
||||||
|
|
||||||
|
msgid "Time Entry Report"
|
||||||
|
msgstr "タイムエントリレポート"
|
||||||
|
|
||||||
|
msgid "Time Sheet Report"
|
||||||
|
msgstr "タイムシートのレポート"
|
||||||
|
|
||||||
|
msgid "Time Tracking Report"
|
||||||
|
msgstr "タイムトラッキングレポート"
|
||||||
|
|
||||||
|
msgid "Data"
|
||||||
|
msgstr "データ"
|
||||||
|
|
||||||
|
msgid "Processed"
|
||||||
|
msgstr "処理されました"
|
||||||
|
|
||||||
|
msgid "Not Processed"
|
||||||
|
msgstr "処理されていません"
|
||||||
|
|
||||||
|
msgid "Elementary Proficiency"
|
||||||
|
msgstr "小学校能力"
|
||||||
|
|
||||||
|
msgid "Limited Working Proficiency"
|
||||||
|
msgstr "リミテッド作業能力"
|
||||||
|
|
||||||
|
msgid "Professional Working Proficiency"
|
||||||
|
msgstr "プロフェッショナルの作業能力"
|
||||||
|
|
||||||
|
msgid "Full Professional Proficiency"
|
||||||
|
msgstr "完全なプロフェッショナル能力"
|
||||||
|
|
||||||
|
msgid "Native or Bilingual Proficiency"
|
||||||
|
msgstr "母国語またはバイリンガル"
|
||||||
|
|
||||||
|
msgid "Pending"
|
||||||
|
msgstr "保留中"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "承認"
|
||||||
|
|
||||||
|
msgid "Rejected"
|
||||||
|
msgstr "拒否されました"
|
||||||
|
|
||||||
|
msgid "Cancelled"
|
||||||
|
msgstr "キャンセル"
|
||||||
|
|
||||||
|
msgid "Continue"
|
||||||
|
msgstr "持続する"
|
||||||
|
|
||||||
|
msgid "Cancellation Requested"
|
||||||
|
msgstr "キャンセル要求"
|
||||||
|
|
||||||
|
msgid "Completed"
|
||||||
|
msgstr "完成しました"
|
||||||
|
|
||||||
|
msgid "Discussions"
|
||||||
|
msgstr "議論"
|
||||||
|
|
||||||
|
msgid "Load More"
|
||||||
|
msgstr "以上の負荷"
|
||||||
|
|
||||||
|
msgid "Show More"
|
||||||
|
msgstr "もっと見せる"
|
||||||
|
|
||||||
|
msgid "Show Less"
|
||||||
|
msgstr "レスを表示"
|
||||||
|
|
||||||
|
msgid "Publish"
|
||||||
|
msgstr "出版します"
|
||||||
|
|
||||||
|
msgid "Announcements"
|
||||||
|
msgstr "お知らせ"
|
||||||
|
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "送ります"
|
||||||
|
|
||||||
|
msgid "Display"
|
||||||
|
msgstr "表示"
|
||||||
|
|
||||||
|
msgid "Public"
|
||||||
|
msgstr "パブリック"
|
||||||
|
|
||||||
|
msgid "View Announcements"
|
||||||
|
msgstr "ビューのお知らせ"
|
||||||
|
|
||||||
|
msgid "Conversations"
|
||||||
|
msgstr "会話"
|
||||||
|
|
||||||
|
msgid "Start Now"
|
||||||
|
msgstr "今すぐ開始"
|
||||||
|
|||||||
306
core/lang/pl.po
306
core/lang/pl.po
@@ -1597,3 +1597,309 @@ msgstr "Zastosować"
|
|||||||
|
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Plecy"
|
msgstr "Plecy"
|
||||||
|
|
||||||
|
msgid "Hours in Time Sheets"
|
||||||
|
msgstr "Godzin w kartach czasu"
|
||||||
|
|
||||||
|
msgid "HR form"
|
||||||
|
msgstr "Formularz HR"
|
||||||
|
|
||||||
|
msgid "HR Form Management"
|
||||||
|
msgstr "Formularz Zarządzanie HR"
|
||||||
|
|
||||||
|
msgid "Form Name"
|
||||||
|
msgstr "Nazwa formularza"
|
||||||
|
|
||||||
|
msgid "Fields"
|
||||||
|
msgstr "pola"
|
||||||
|
|
||||||
|
msgid "Employee Froms"
|
||||||
|
msgstr "froms pracownik"
|
||||||
|
|
||||||
|
msgid "Share Departments"
|
||||||
|
msgstr "Departamenty dzielą"
|
||||||
|
|
||||||
|
msgid "Share Employees"
|
||||||
|
msgstr "Pracownicy Share"
|
||||||
|
|
||||||
|
msgid "Data Importers"
|
||||||
|
msgstr "Importerzy danych"
|
||||||
|
|
||||||
|
msgid "Data Import Files"
|
||||||
|
msgstr "Pliki importu danych"
|
||||||
|
|
||||||
|
msgid "Data Type"
|
||||||
|
msgstr "Typ danych"
|
||||||
|
|
||||||
|
msgid "Columns"
|
||||||
|
msgstr "kolumny"
|
||||||
|
|
||||||
|
msgid "Field Title"
|
||||||
|
msgstr "pole Tytuł"
|
||||||
|
|
||||||
|
msgid "Depends On"
|
||||||
|
msgstr "Zależy od"
|
||||||
|
|
||||||
|
msgid "Depends On Field"
|
||||||
|
msgstr "Zależy na pole"
|
||||||
|
|
||||||
|
msgid "is Key Field"
|
||||||
|
msgstr "Pole jest klucz"
|
||||||
|
|
||||||
|
msgid "is ID Field"
|
||||||
|
msgstr "Pole jest ID"
|
||||||
|
|
||||||
|
msgid "Data Import Definitions"
|
||||||
|
msgstr "Import danych Definicje"
|
||||||
|
|
||||||
|
msgid "File to Import"
|
||||||
|
msgstr "Plik do importu"
|
||||||
|
|
||||||
|
msgid "Last Export Results"
|
||||||
|
msgstr "Ostatnio Wyniki eksportu"
|
||||||
|
|
||||||
|
msgid "Time and Attendance"
|
||||||
|
msgstr "Rejestracja czasu pracy"
|
||||||
|
|
||||||
|
msgid "Leave Timeline"
|
||||||
|
msgstr "Zostaw Timeline"
|
||||||
|
|
||||||
|
msgid "Insights"
|
||||||
|
msgstr "Insights"
|
||||||
|
|
||||||
|
msgid "Api Access"
|
||||||
|
msgstr "Dostęp do API"
|
||||||
|
|
||||||
|
msgid "Change User Password"
|
||||||
|
msgstr "Zmiana użytkownika Hasło"
|
||||||
|
|
||||||
|
msgid "New Password"
|
||||||
|
msgstr "nowe hasło"
|
||||||
|
|
||||||
|
msgid "Confirm Password"
|
||||||
|
msgstr "Potwierdź hasło"
|
||||||
|
|
||||||
|
msgid "Change Password"
|
||||||
|
msgstr "Zmień hasło"
|
||||||
|
|
||||||
|
msgid "Not Now"
|
||||||
|
msgstr "Nie teraz"
|
||||||
|
|
||||||
|
msgid "Contact Information"
|
||||||
|
msgstr "Informacje kontaktowe"
|
||||||
|
|
||||||
|
msgid "Job Details"
|
||||||
|
msgstr "Szczegóły pracy"
|
||||||
|
|
||||||
|
msgid "Edit Info"
|
||||||
|
msgstr "Edytuj informacje"
|
||||||
|
|
||||||
|
msgid "Upload Profile Image"
|
||||||
|
msgstr "Prześlij zdjęcie profilowe"
|
||||||
|
|
||||||
|
msgid "Delete Profile Image"
|
||||||
|
msgstr "Usuń Profil obraz"
|
||||||
|
|
||||||
|
msgid "Direct Reports"
|
||||||
|
msgstr "Bezpośrednie raporty"
|
||||||
|
|
||||||
|
msgid "Other Details"
|
||||||
|
msgstr "Inne szczegóły"
|
||||||
|
|
||||||
|
msgid "Family"
|
||||||
|
msgstr "Rodzina"
|
||||||
|
|
||||||
|
msgid "Custom Fields"
|
||||||
|
msgstr "Pola niestandardowe"
|
||||||
|
|
||||||
|
msgid "Means of Transportation"
|
||||||
|
msgstr "Środki transportu"
|
||||||
|
|
||||||
|
msgid "Plane"
|
||||||
|
msgstr "Samolot"
|
||||||
|
|
||||||
|
msgid "Rail"
|
||||||
|
msgstr "Szyna"
|
||||||
|
|
||||||
|
msgid "Taxi"
|
||||||
|
msgstr "Taxi"
|
||||||
|
|
||||||
|
msgid "Own Vehicle"
|
||||||
|
msgstr "Własny pojazd"
|
||||||
|
|
||||||
|
msgid "Rented Vehicle"
|
||||||
|
msgstr "wynajęty pojazd"
|
||||||
|
|
||||||
|
msgid "Female"
|
||||||
|
msgstr "Płeć żeńska"
|
||||||
|
|
||||||
|
msgid "Male"
|
||||||
|
msgstr "Męski"
|
||||||
|
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "Aktywny"
|
||||||
|
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "Nieaktywny"
|
||||||
|
|
||||||
|
msgid "Draft"
|
||||||
|
msgstr "Wersja robocza"
|
||||||
|
|
||||||
|
msgid "Not Clocked In"
|
||||||
|
msgstr "W nie Clocked"
|
||||||
|
|
||||||
|
msgid "Clocked In"
|
||||||
|
msgstr "W taktowany"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "Plik"
|
||||||
|
|
||||||
|
msgid "Active Employee Report"
|
||||||
|
msgstr "Pracownik aktywny Report"
|
||||||
|
|
||||||
|
msgid "Employee Attendance Report"
|
||||||
|
msgstr "Pracownik Frekwencja Report"
|
||||||
|
|
||||||
|
msgid "Employee Details Report"
|
||||||
|
msgstr "Pracownik Szczegóły Report"
|
||||||
|
|
||||||
|
msgid "Employee Leave Entitlement"
|
||||||
|
msgstr "Pracownik Leave Prawo"
|
||||||
|
|
||||||
|
msgid "Employee Leaves Report"
|
||||||
|
msgstr "Pracownik Liście Report"
|
||||||
|
|
||||||
|
msgid "Employee Time Entry Report"
|
||||||
|
msgstr "Pracownik Czas Zgłoś Entry"
|
||||||
|
|
||||||
|
msgid "Employee Time Sheet Report"
|
||||||
|
msgstr "Etat Arkusz Report"
|
||||||
|
|
||||||
|
msgid "Employee Time Tracking Report"
|
||||||
|
msgstr "Pracownik Time Tracking Report"
|
||||||
|
|
||||||
|
msgid "Expense Report"
|
||||||
|
msgstr "Raport z wydatków"
|
||||||
|
|
||||||
|
msgid "New Hires Employee Report"
|
||||||
|
msgstr "Nowych pracowników Employee Report"
|
||||||
|
|
||||||
|
msgid "Overtime Report"
|
||||||
|
msgstr "Raport nadgodziny"
|
||||||
|
|
||||||
|
msgid "Overtime Request Report"
|
||||||
|
msgstr "Nadgodziny Zapytanie Report"
|
||||||
|
|
||||||
|
msgid "Overtime Summary Report"
|
||||||
|
msgstr "Nadgodziny Raport zbiorczy"
|
||||||
|
|
||||||
|
msgid "Payroll Meta Data Export"
|
||||||
|
msgstr "Płace Meta Data Export"
|
||||||
|
|
||||||
|
msgid "Terminated Employee Report"
|
||||||
|
msgstr "Raport zakończony Employee"
|
||||||
|
|
||||||
|
msgid "Travel Request Report"
|
||||||
|
msgstr "Zapytanie Travel Report"
|
||||||
|
|
||||||
|
msgid "Attendance Report"
|
||||||
|
msgstr "Lista obecności"
|
||||||
|
|
||||||
|
msgid "Client Project Time Report"
|
||||||
|
msgstr "Klient Projekt Raport czasowy"
|
||||||
|
|
||||||
|
msgid "Download Payslips"
|
||||||
|
msgstr "Pobierz paski wypłat pensji"
|
||||||
|
|
||||||
|
msgid "Leaves Report"
|
||||||
|
msgstr "Raport pozostawia"
|
||||||
|
|
||||||
|
msgid "Time Entry Report"
|
||||||
|
msgstr "Czas Zgłoś Entry"
|
||||||
|
|
||||||
|
msgid "Time Sheet Report"
|
||||||
|
msgstr "Czas Sheet Report"
|
||||||
|
|
||||||
|
msgid "Time Tracking Report"
|
||||||
|
msgstr "Time Tracking Report"
|
||||||
|
|
||||||
|
msgid "Data"
|
||||||
|
msgstr "Dane"
|
||||||
|
|
||||||
|
msgid "Processed"
|
||||||
|
msgstr "Obrobiony"
|
||||||
|
|
||||||
|
msgid "Not Processed"
|
||||||
|
msgstr "Nieprzetworzony"
|
||||||
|
|
||||||
|
msgid "Elementary Proficiency"
|
||||||
|
msgstr "Podstawowa znajomość"
|
||||||
|
|
||||||
|
msgid "Limited Working Proficiency"
|
||||||
|
msgstr "Ograniczona wydajność pracy"
|
||||||
|
|
||||||
|
msgid "Professional Working Proficiency"
|
||||||
|
msgstr "Profesjonalna biegłość w pracy"
|
||||||
|
|
||||||
|
msgid "Full Professional Proficiency"
|
||||||
|
msgstr "Pełna biegłość zawodowa"
|
||||||
|
|
||||||
|
msgid "Native or Bilingual Proficiency"
|
||||||
|
msgstr "Język ojczysty lub biegłość dwujęzyczna"
|
||||||
|
|
||||||
|
msgid "Pending"
|
||||||
|
msgstr "W oczekiwaniu"
|
||||||
|
|
||||||
|
msgid "Approved"
|
||||||
|
msgstr "Zatwierdzony"
|
||||||
|
|
||||||
|
msgid "Rejected"
|
||||||
|
msgstr "odrzucony"
|
||||||
|
|
||||||
|
msgid "Cancelled"
|
||||||
|
msgstr "Anulowany"
|
||||||
|
|
||||||
|
msgid "Continue"
|
||||||
|
msgstr "dalej"
|
||||||
|
|
||||||
|
msgid "Cancellation Requested"
|
||||||
|
msgstr "Rezygnacja Zamówiony"
|
||||||
|
|
||||||
|
msgid "Completed"
|
||||||
|
msgstr "Zakończony"
|
||||||
|
|
||||||
|
msgid "Discussions"
|
||||||
|
msgstr "dyskusje"
|
||||||
|
|
||||||
|
msgid "Load More"
|
||||||
|
msgstr "Załaduj więcej"
|
||||||
|
|
||||||
|
msgid "Show More"
|
||||||
|
msgstr "Pokaż więcej"
|
||||||
|
|
||||||
|
msgid "Show Less"
|
||||||
|
msgstr "Pokaż mniej"
|
||||||
|
|
||||||
|
msgid "Publish"
|
||||||
|
msgstr "Publikować"
|
||||||
|
|
||||||
|
msgid "Announcements"
|
||||||
|
msgstr "Ogłoszenia"
|
||||||
|
|
||||||
|
msgid "Send"
|
||||||
|
msgstr "Wysłać"
|
||||||
|
|
||||||
|
msgid "Display"
|
||||||
|
msgstr "Pokaz"
|
||||||
|
|
||||||
|
msgid "Public"
|
||||||
|
msgstr "Publiczny"
|
||||||
|
|
||||||
|
msgid "View Announcements"
|
||||||
|
msgstr "Zobacz ogłoszenia"
|
||||||
|
|
||||||
|
msgid "Conversations"
|
||||||
|
msgstr "rozmowy"
|
||||||
|
|
||||||
|
msgid "Start Now"
|
||||||
|
msgstr "Zacząć teraz"
|
||||||
|
|||||||
668
core/lang/zh.po
668
core/lang/zh.po
File diff suppressed because it is too large
Load Diff
951
core/lib/Mail/RFC822.php
Normal file
951
core/lib/Mail/RFC822.php
Normal file
@@ -0,0 +1,951 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* RFC 822 Email address list validation Utility
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* LICENSE:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2010, Richard Heyes
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* o Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* o Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* o The names of the authors may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @category Mail
|
||||||
|
* @package Mail
|
||||||
|
* @author Richard Heyes <richard@phpguru.org>
|
||||||
|
* @author Chuck Hagenbuch <chuck@horde.org
|
||||||
|
* @copyright 2001-2010 Richard Heyes
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||||
|
* @version CVS: $Id: RFC822.php 294749 2010-02-08 08:22:25Z clockwerx $
|
||||||
|
* @link http://pear.php.net/package/Mail/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RFC 822 Email address list validation Utility
|
||||||
|
*
|
||||||
|
* What is it?
|
||||||
|
*
|
||||||
|
* This class will take an address string, and parse it into it's consituent
|
||||||
|
* parts, be that either addresses, groups, or combinations. Nested groups
|
||||||
|
* are not supported. The structure it returns is pretty straight forward,
|
||||||
|
* and is similar to that provided by the imap_rfc822_parse_adrlist(). Use
|
||||||
|
* print_r() to view the structure.
|
||||||
|
*
|
||||||
|
* How do I use it?
|
||||||
|
*
|
||||||
|
* $address_string = 'My Group: "Richard" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;';
|
||||||
|
* $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true)
|
||||||
|
* print_r($structure);
|
||||||
|
*
|
||||||
|
* @author Richard Heyes <richard@phpguru.org>
|
||||||
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
||||||
|
* @version $Revision: 294749 $
|
||||||
|
* @license BSD
|
||||||
|
* @package Mail
|
||||||
|
*/
|
||||||
|
class Mail_RFC822 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address being parsed by the RFC822 object.
|
||||||
|
* @var string $address
|
||||||
|
*/
|
||||||
|
var $address = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default domain to use for unqualified addresses.
|
||||||
|
* @var string $default_domain
|
||||||
|
*/
|
||||||
|
var $default_domain = 'localhost';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we return a nested array showing groups, or flatten everything?
|
||||||
|
* @var boolean $nestGroups
|
||||||
|
*/
|
||||||
|
var $nestGroups = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to validate atoms for non-ascii characters.
|
||||||
|
* @var boolean $validate
|
||||||
|
*/
|
||||||
|
var $validate = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of raw addresses built up as we parse.
|
||||||
|
* @var array $addresses
|
||||||
|
*/
|
||||||
|
var $addresses = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The final array of parsed address information that we build up.
|
||||||
|
* @var array $structure
|
||||||
|
*/
|
||||||
|
var $structure = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current error message, if any.
|
||||||
|
* @var string $error
|
||||||
|
*/
|
||||||
|
var $error = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal counter/pointer.
|
||||||
|
* @var integer $index
|
||||||
|
*/
|
||||||
|
var $index = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of groups that have been found in the address list.
|
||||||
|
* @var integer $num_groups
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $num_groups = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable so that we can tell whether or not we're inside a
|
||||||
|
* Mail_RFC822 object.
|
||||||
|
* @var boolean $mailRFC822
|
||||||
|
*/
|
||||||
|
var $mailRFC822 = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A limit after which processing stops
|
||||||
|
* @var int $limit
|
||||||
|
*/
|
||||||
|
var $limit = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the object. The address must either be set here or when
|
||||||
|
* calling parseAddressList(). One or the other.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $address The address(es) to validate.
|
||||||
|
* @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
|
||||||
|
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
|
||||||
|
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
|
||||||
|
*
|
||||||
|
* @return object Mail_RFC822 A new Mail_RFC822 object.
|
||||||
|
*/
|
||||||
|
function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
|
||||||
|
{
|
||||||
|
if (isset($address)) $this->address = $address;
|
||||||
|
if (isset($default_domain)) $this->default_domain = $default_domain;
|
||||||
|
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
|
||||||
|
if (isset($validate)) $this->validate = $validate;
|
||||||
|
if (isset($limit)) $this->limit = $limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the whole process. The address must either be set here
|
||||||
|
* or when creating the object. One or the other.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $address The address(es) to validate.
|
||||||
|
* @param string $default_domain Default domain/host etc.
|
||||||
|
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
|
||||||
|
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
|
||||||
|
*
|
||||||
|
* @return array A structured array of addresses.
|
||||||
|
*/
|
||||||
|
function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
|
||||||
|
{
|
||||||
|
if (!isset($this) || !isset($this->mailRFC822)) {
|
||||||
|
$obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
|
||||||
|
return $obj->parseAddressList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($address)) $this->address = $address;
|
||||||
|
if (isset($default_domain)) $this->default_domain = $default_domain;
|
||||||
|
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
|
||||||
|
if (isset($validate)) $this->validate = $validate;
|
||||||
|
if (isset($limit)) $this->limit = $limit;
|
||||||
|
|
||||||
|
$this->structure = array();
|
||||||
|
$this->addresses = array();
|
||||||
|
$this->error = null;
|
||||||
|
$this->index = null;
|
||||||
|
|
||||||
|
// Unfold any long lines in $this->address.
|
||||||
|
$this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
|
||||||
|
$this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
|
||||||
|
|
||||||
|
while ($this->address = $this->_splitAddresses($this->address));
|
||||||
|
|
||||||
|
if ($this->address === false || isset($this->error)) {
|
||||||
|
require_once 'PEAR.php';
|
||||||
|
return PEAR::raiseError($this->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate each address individually. If we encounter an invalid
|
||||||
|
// address, stop iterating and return an error immediately.
|
||||||
|
foreach ($this->addresses as $address) {
|
||||||
|
$valid = $this->_validateAddress($address);
|
||||||
|
|
||||||
|
if ($valid === false || isset($this->error)) {
|
||||||
|
require_once 'PEAR.php';
|
||||||
|
return PEAR::raiseError($this->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->nestGroups) {
|
||||||
|
$this->structure = array_merge($this->structure, $valid);
|
||||||
|
} else {
|
||||||
|
$this->structure[] = $valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits an address into separate addresses.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $address The addresses to split.
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function _splitAddresses($address)
|
||||||
|
{
|
||||||
|
if (!empty($this->limit) && count($this->addresses) == $this->limit) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_isGroup($address) && !isset($this->error)) {
|
||||||
|
$split_char = ';';
|
||||||
|
$is_group = true;
|
||||||
|
} elseif (!isset($this->error)) {
|
||||||
|
$split_char = ',';
|
||||||
|
$is_group = false;
|
||||||
|
} elseif (isset($this->error)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the string based on the above ten or so lines.
|
||||||
|
$parts = explode($split_char, $address);
|
||||||
|
$string = $this->_splitCheck($parts, $split_char);
|
||||||
|
|
||||||
|
// If a group...
|
||||||
|
if ($is_group) {
|
||||||
|
// If $string does not contain a colon outside of
|
||||||
|
// brackets/quotes etc then something's fubar.
|
||||||
|
|
||||||
|
// First check there's a colon at all:
|
||||||
|
if (strpos($string, ':') === false) {
|
||||||
|
$this->error = 'Invalid address: ' . $string;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check it's outside of brackets/quotes:
|
||||||
|
if (!$this->_splitCheck(explode(':', $string), ':')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must have a group at this point, so increase the counter:
|
||||||
|
$this->num_groups++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// $string now contains the first full address/group.
|
||||||
|
// Add to the addresses array.
|
||||||
|
$this->addresses[] = array(
|
||||||
|
'address' => trim($string),
|
||||||
|
'group' => $is_group
|
||||||
|
);
|
||||||
|
|
||||||
|
// Remove the now stored address from the initial line, the +1
|
||||||
|
// is to account for the explode character.
|
||||||
|
$address = trim(substr($address, strlen($string) + 1));
|
||||||
|
|
||||||
|
// If the next char is a comma and this was a group, then
|
||||||
|
// there are more addresses, otherwise, if there are any more
|
||||||
|
// chars, then there is another address.
|
||||||
|
if ($is_group && substr($address, 0, 1) == ','){
|
||||||
|
$address = trim(substr($address, 1));
|
||||||
|
return $address;
|
||||||
|
|
||||||
|
} elseif (strlen($address) > 0) {
|
||||||
|
return $address;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you got here then something's off
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for a group at the start of the string.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $address The address to check.
|
||||||
|
* @return boolean Whether or not there is a group at the start of the string.
|
||||||
|
*/
|
||||||
|
function _isGroup($address)
|
||||||
|
{
|
||||||
|
// First comma not in quotes, angles or escaped:
|
||||||
|
$parts = explode(',', $address);
|
||||||
|
$string = $this->_splitCheck($parts, ',');
|
||||||
|
|
||||||
|
// Now we have the first address, we can reliably check for a
|
||||||
|
// group by searching for a colon that's not escaped or in
|
||||||
|
// quotes or angle brackets.
|
||||||
|
if (count($parts = explode(':', $string)) > 1) {
|
||||||
|
$string2 = $this->_splitCheck($parts, ':');
|
||||||
|
return ($string2 !== $string);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common function that will check an exploded string.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param array $parts The exloded string.
|
||||||
|
* @param string $char The char that was exploded on.
|
||||||
|
* @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
|
||||||
|
*/
|
||||||
|
function _splitCheck($parts, $char)
|
||||||
|
{
|
||||||
|
$string = $parts[0];
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($parts); $i++) {
|
||||||
|
if ($this->_hasUnclosedQuotes($string)
|
||||||
|
|| $this->_hasUnclosedBrackets($string, '<>')
|
||||||
|
|| $this->_hasUnclosedBrackets($string, '[]')
|
||||||
|
|| $this->_hasUnclosedBrackets($string, '()')
|
||||||
|
|| substr($string, -1) == '\\') {
|
||||||
|
if (isset($parts[$i + 1])) {
|
||||||
|
$string = $string . $char . $parts[$i + 1];
|
||||||
|
} else {
|
||||||
|
$this->error = 'Invalid address spec. Unclosed bracket or quotes';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->index = $i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a string has unclosed quotes or not.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $string The string to check.
|
||||||
|
* @return boolean True if there are unclosed quotes inside the string,
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
function _hasUnclosedQuotes($string)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
$iMax = strlen($string);
|
||||||
|
$in_quote = false;
|
||||||
|
$i = $slashes = 0;
|
||||||
|
|
||||||
|
for (; $i < $iMax; ++$i) {
|
||||||
|
switch ($string[$i]) {
|
||||||
|
case '\\':
|
||||||
|
++$slashes;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
if ($slashes % 2 == 0) {
|
||||||
|
$in_quote = !$in_quote;
|
||||||
|
}
|
||||||
|
// Fall through to default action below.
|
||||||
|
|
||||||
|
default:
|
||||||
|
$slashes = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $in_quote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a string has an unclosed brackets or not. IMPORTANT:
|
||||||
|
* This function handles both angle brackets and square brackets;
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $string The string to check.
|
||||||
|
* @param string $chars The characters to check for.
|
||||||
|
* @return boolean True if there are unclosed brackets inside the string, false otherwise.
|
||||||
|
*/
|
||||||
|
function _hasUnclosedBrackets($string, $chars)
|
||||||
|
{
|
||||||
|
$num_angle_start = substr_count($string, $chars[0]);
|
||||||
|
$num_angle_end = substr_count($string, $chars[1]);
|
||||||
|
|
||||||
|
$this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
|
||||||
|
$this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
|
||||||
|
|
||||||
|
if ($num_angle_start < $num_angle_end) {
|
||||||
|
$this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return ($num_angle_start > $num_angle_end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub function that is used only by hasUnclosedBrackets().
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $string The string to check.
|
||||||
|
* @param integer &$num The number of occurences.
|
||||||
|
* @param string $char The character to count.
|
||||||
|
* @return integer The number of occurences of $char in $string, adjusted for backslashes.
|
||||||
|
*/
|
||||||
|
function _hasUnclosedBracketsSub($string, &$num, $char)
|
||||||
|
{
|
||||||
|
$parts = explode($char, $string);
|
||||||
|
for ($i = 0; $i < count($parts); $i++){
|
||||||
|
if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
|
||||||
|
$num--;
|
||||||
|
if (isset($parts[$i + 1]))
|
||||||
|
$parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to begin checking the address.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $address The address to validate.
|
||||||
|
* @return mixed False on failure, or a structured array of address information on success.
|
||||||
|
*/
|
||||||
|
function _validateAddress($address)
|
||||||
|
{
|
||||||
|
$is_group = false;
|
||||||
|
$addresses = array();
|
||||||
|
|
||||||
|
if ($address['group']) {
|
||||||
|
$is_group = true;
|
||||||
|
|
||||||
|
// Get the group part of the name
|
||||||
|
$parts = explode(':', $address['address']);
|
||||||
|
$groupname = $this->_splitCheck($parts, ':');
|
||||||
|
$structure = array();
|
||||||
|
|
||||||
|
// And validate the group part of the name.
|
||||||
|
if (!$this->_validatePhrase($groupname)){
|
||||||
|
$this->error = 'Group name did not validate.';
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// Don't include groups if we are not nesting
|
||||||
|
// them. This avoids returning invalid addresses.
|
||||||
|
if ($this->nestGroups) {
|
||||||
|
$structure = new stdClass;
|
||||||
|
$structure->groupname = $groupname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a group then split on comma and put into an array.
|
||||||
|
// Otherwise, Just put the whole address in an array.
|
||||||
|
if ($is_group) {
|
||||||
|
while (strlen($address['address']) > 0) {
|
||||||
|
$parts = explode(',', $address['address']);
|
||||||
|
$addresses[] = $this->_splitCheck($parts, ',');
|
||||||
|
$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$addresses[] = $address['address'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that $addresses is set, if address like this:
|
||||||
|
// Groupname:;
|
||||||
|
// Then errors were appearing.
|
||||||
|
if (!count($addresses)){
|
||||||
|
$this->error = 'Empty group.';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim the whitespace from all of the address strings.
|
||||||
|
array_map('trim', $addresses);
|
||||||
|
|
||||||
|
// Validate each mailbox.
|
||||||
|
// Format could be one of: name <geezer@domain.com>
|
||||||
|
// geezer@domain.com
|
||||||
|
// geezer
|
||||||
|
// ... or any other format valid by RFC 822.
|
||||||
|
for ($i = 0; $i < count($addresses); $i++) {
|
||||||
|
if (!$this->validateMailbox($addresses[$i])) {
|
||||||
|
if (empty($this->error)) {
|
||||||
|
$this->error = 'Validation failed for: ' . $addresses[$i];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nested format
|
||||||
|
if ($this->nestGroups) {
|
||||||
|
if ($is_group) {
|
||||||
|
$structure->addresses = $addresses;
|
||||||
|
} else {
|
||||||
|
$structure = $addresses[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flat format
|
||||||
|
} else {
|
||||||
|
if ($is_group) {
|
||||||
|
$structure = array_merge($structure, $addresses);
|
||||||
|
} else {
|
||||||
|
$structure = $addresses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate a phrase.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $phrase The phrase to check.
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function _validatePhrase($phrase)
|
||||||
|
{
|
||||||
|
// Splits on one or more Tab or space.
|
||||||
|
$parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
|
||||||
|
$phrase_parts = array();
|
||||||
|
while (count($parts) > 0){
|
||||||
|
$phrase_parts[] = $this->_splitCheck($parts, ' ');
|
||||||
|
for ($i = 0; $i < $this->index + 1; $i++)
|
||||||
|
array_shift($parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($phrase_parts as $part) {
|
||||||
|
// If quoted string:
|
||||||
|
if (substr($part, 0, 1) == '"') {
|
||||||
|
if (!$this->_validateQuotedString($part)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise it's an atom:
|
||||||
|
if (!$this->_validateAtom($part)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate an atom which from rfc822 is:
|
||||||
|
* atom = 1*<any CHAR except specials, SPACE and CTLs>
|
||||||
|
*
|
||||||
|
* If validation ($this->validate) has been turned off, then
|
||||||
|
* validateAtom() doesn't actually check anything. This is so that you
|
||||||
|
* can split a list of addresses up before encoding personal names
|
||||||
|
* (umlauts, etc.), for example.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $atom The string to check.
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function _validateAtom($atom)
|
||||||
|
{
|
||||||
|
if (!$this->validate) {
|
||||||
|
// Validation has been turned off; assume the atom is okay.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for any char from ASCII 0 - ASCII 127
|
||||||
|
if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for specials:
|
||||||
|
if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for control characters (ASCII 0-31):
|
||||||
|
if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate quoted string, which is:
|
||||||
|
* quoted-string = <"> *(qtext/quoted-pair) <">
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $qstring The string to check
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function _validateQuotedString($qstring)
|
||||||
|
{
|
||||||
|
// Leading and trailing "
|
||||||
|
$qstring = substr($qstring, 1, -1);
|
||||||
|
|
||||||
|
// Perform check, removing quoted characters first.
|
||||||
|
return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate a mailbox, which is:
|
||||||
|
* mailbox = addr-spec ; simple address
|
||||||
|
* / phrase route-addr ; name and route-addr
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string &$mailbox The string to check.
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function validateMailbox(&$mailbox)
|
||||||
|
{
|
||||||
|
// A couple of defaults.
|
||||||
|
$phrase = '';
|
||||||
|
$comment = '';
|
||||||
|
$comments = array();
|
||||||
|
|
||||||
|
// Catch any RFC822 comments and store them separately.
|
||||||
|
$_mailbox = $mailbox;
|
||||||
|
while (strlen(trim($_mailbox)) > 0) {
|
||||||
|
$parts = explode('(', $_mailbox);
|
||||||
|
$before_comment = $this->_splitCheck($parts, '(');
|
||||||
|
if ($before_comment != $_mailbox) {
|
||||||
|
// First char should be a (.
|
||||||
|
$comment = substr(str_replace($before_comment, '', $_mailbox), 1);
|
||||||
|
$parts = explode(')', $comment);
|
||||||
|
$comment = $this->_splitCheck($parts, ')');
|
||||||
|
$comments[] = $comment;
|
||||||
|
|
||||||
|
// +2 is for the brackets
|
||||||
|
$_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($comments as $comment) {
|
||||||
|
$mailbox = str_replace("($comment)", '', $mailbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mailbox = trim($mailbox);
|
||||||
|
|
||||||
|
// Check for name + route-addr
|
||||||
|
if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
|
||||||
|
$parts = explode('<', $mailbox);
|
||||||
|
$name = $this->_splitCheck($parts, '<');
|
||||||
|
|
||||||
|
$phrase = trim($name);
|
||||||
|
$route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
|
||||||
|
|
||||||
|
if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only got addr-spec
|
||||||
|
} else {
|
||||||
|
// First snip angle brackets if present.
|
||||||
|
if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
|
||||||
|
$addr_spec = substr($mailbox, 1, -1);
|
||||||
|
} else {
|
||||||
|
$addr_spec = $mailbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the object that will be returned.
|
||||||
|
$mbox = new stdClass();
|
||||||
|
|
||||||
|
// Add the phrase (even if empty) and comments
|
||||||
|
$mbox->personal = $phrase;
|
||||||
|
$mbox->comment = isset($comments) ? $comments : array();
|
||||||
|
|
||||||
|
if (isset($route_addr)) {
|
||||||
|
$mbox->mailbox = $route_addr['local_part'];
|
||||||
|
$mbox->host = $route_addr['domain'];
|
||||||
|
$route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
|
||||||
|
} else {
|
||||||
|
$mbox->mailbox = $addr_spec['local_part'];
|
||||||
|
$mbox->host = $addr_spec['domain'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mailbox = $mbox;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function validates a route-addr which is:
|
||||||
|
* route-addr = "<" [route] addr-spec ">"
|
||||||
|
*
|
||||||
|
* Angle brackets have already been removed at the point of
|
||||||
|
* getting to this function.
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $route_addr The string to check.
|
||||||
|
* @return mixed False on failure, or an array containing validated address/route information on success.
|
||||||
|
*/
|
||||||
|
function _validateRouteAddr($route_addr)
|
||||||
|
{
|
||||||
|
// Check for colon.
|
||||||
|
if (strpos($route_addr, ':') !== false) {
|
||||||
|
$parts = explode(':', $route_addr);
|
||||||
|
$route = $this->_splitCheck($parts, ':');
|
||||||
|
} else {
|
||||||
|
$route = $route_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If $route is same as $route_addr then the colon was in
|
||||||
|
// quotes or brackets or, of course, non existent.
|
||||||
|
if ($route === $route_addr){
|
||||||
|
unset($route);
|
||||||
|
$addr_spec = $route_addr;
|
||||||
|
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Validate route part.
|
||||||
|
if (($route = $this->_validateRoute($route)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$addr_spec = substr($route_addr, strlen($route . ':'));
|
||||||
|
|
||||||
|
// Validate addr-spec part.
|
||||||
|
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($route)) {
|
||||||
|
$return['adl'] = $route;
|
||||||
|
} else {
|
||||||
|
$return['adl'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$return = array_merge($return, $addr_spec);
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate a route, which is:
|
||||||
|
* route = 1#("@" domain) ":"
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $route The string to check.
|
||||||
|
* @return mixed False on failure, or the validated $route on success.
|
||||||
|
*/
|
||||||
|
function _validateRoute($route)
|
||||||
|
{
|
||||||
|
// Split on comma.
|
||||||
|
$domains = explode(',', trim($route));
|
||||||
|
|
||||||
|
foreach ($domains as $domain) {
|
||||||
|
$domain = str_replace('@', '', trim($domain));
|
||||||
|
if (!$this->_validateDomain($domain)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $route;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate a domain, though this is not quite what
|
||||||
|
* you expect of a strict internet domain.
|
||||||
|
*
|
||||||
|
* domain = sub-domain *("." sub-domain)
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $domain The string to check.
|
||||||
|
* @return mixed False on failure, or the validated domain on success.
|
||||||
|
*/
|
||||||
|
function _validateDomain($domain)
|
||||||
|
{
|
||||||
|
// Note the different use of $subdomains and $sub_domains
|
||||||
|
$subdomains = explode('.', $domain);
|
||||||
|
|
||||||
|
while (count($subdomains) > 0) {
|
||||||
|
$sub_domains[] = $this->_splitCheck($subdomains, '.');
|
||||||
|
for ($i = 0; $i < $this->index + 1; $i++)
|
||||||
|
array_shift($subdomains);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($sub_domains as $sub_domain) {
|
||||||
|
if (!$this->_validateSubdomain(trim($sub_domain)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Managed to get here, so return input.
|
||||||
|
return $domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate a subdomain:
|
||||||
|
* subdomain = domain-ref / domain-literal
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $subdomain The string to check.
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function _validateSubdomain($subdomain)
|
||||||
|
{
|
||||||
|
if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
|
||||||
|
if (!$this->_validateDliteral($arr[1])) return false;
|
||||||
|
} else {
|
||||||
|
if (!$this->_validateAtom($subdomain)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Got here, so return successful.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate a domain literal:
|
||||||
|
* domain-literal = "[" *(dtext / quoted-pair) "]"
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $dliteral The string to check.
|
||||||
|
* @return boolean Success or failure.
|
||||||
|
*/
|
||||||
|
function _validateDliteral($dliteral)
|
||||||
|
{
|
||||||
|
return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate an addr-spec.
|
||||||
|
*
|
||||||
|
* addr-spec = local-part "@" domain
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $addr_spec The string to check.
|
||||||
|
* @return mixed False on failure, or the validated addr-spec on success.
|
||||||
|
*/
|
||||||
|
function _validateAddrSpec($addr_spec)
|
||||||
|
{
|
||||||
|
$addr_spec = trim($addr_spec);
|
||||||
|
|
||||||
|
// Split on @ sign if there is one.
|
||||||
|
if (strpos($addr_spec, '@') !== false) {
|
||||||
|
$parts = explode('@', $addr_spec);
|
||||||
|
$local_part = $this->_splitCheck($parts, '@');
|
||||||
|
$domain = substr($addr_spec, strlen($local_part . '@'));
|
||||||
|
|
||||||
|
// No @ sign so assume the default domain.
|
||||||
|
} else {
|
||||||
|
$local_part = $addr_spec;
|
||||||
|
$domain = $this->default_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
|
||||||
|
if (($domain = $this->_validateDomain($domain)) === false) return false;
|
||||||
|
|
||||||
|
// Got here so return successful.
|
||||||
|
return array('local_part' => $local_part, 'domain' => $domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to validate the local part of an address:
|
||||||
|
* local-part = word *("." word)
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $local_part
|
||||||
|
* @return mixed False on failure, or the validated local part on success.
|
||||||
|
*/
|
||||||
|
function _validateLocalPart($local_part)
|
||||||
|
{
|
||||||
|
$parts = explode('.', $local_part);
|
||||||
|
$words = array();
|
||||||
|
|
||||||
|
// Split the local_part into words.
|
||||||
|
while (count($parts) > 0){
|
||||||
|
$words[] = $this->_splitCheck($parts, '.');
|
||||||
|
for ($i = 0; $i < $this->index + 1; $i++) {
|
||||||
|
array_shift($parts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate each word.
|
||||||
|
foreach ($words as $word) {
|
||||||
|
// If this word contains an unquoted space, it is invalid. (6.2.4)
|
||||||
|
if (strpos($word, ' ') && $word[0] !== '"')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_validatePhrase(trim($word)) === false) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Managed to get here, so return the input.
|
||||||
|
return $local_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an approximate count of how many addresses are in the
|
||||||
|
* given string. This is APPROXIMATE as it only splits based on a
|
||||||
|
* comma which has no preceding backslash. Could be useful as
|
||||||
|
* large amounts of addresses will end up producing *large*
|
||||||
|
* structures when used with parseAddressList().
|
||||||
|
*
|
||||||
|
* @param string $data Addresses to count
|
||||||
|
* @return int Approximate count
|
||||||
|
*/
|
||||||
|
function approximateCount($data)
|
||||||
|
{
|
||||||
|
return count(preg_split('/(?<!\\\\),/', $data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a email validating function separate to the rest of the
|
||||||
|
* class. It simply validates whether an email is of the common
|
||||||
|
* internet form: <user>@<domain>. This can be sufficient for most
|
||||||
|
* people. Optional stricter mode can be utilised which restricts
|
||||||
|
* mailbox characters allowed to alphanumeric, full stop, hyphen
|
||||||
|
* and underscore.
|
||||||
|
*
|
||||||
|
* @param string $data Address to check
|
||||||
|
* @param boolean $strict Optional stricter mode
|
||||||
|
* @return mixed False if it fails, an indexed array
|
||||||
|
* username/domain if it matches
|
||||||
|
*/
|
||||||
|
function isValidInetAddress($data, $strict = false)
|
||||||
|
{
|
||||||
|
$regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
|
||||||
|
if (preg_match($regex, trim($data), $matches)) {
|
||||||
|
return array($matches[1], $matches[2]);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
168
core/lib/Mail/mail.php
Normal file
168
core/lib/Mail/mail.php
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* internal PHP-mail() implementation of the PEAR Mail:: interface.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* LICENSE:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Chuck Hagenbuch
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* o Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* o Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* o The names of the authors may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @category Mail
|
||||||
|
* @package Mail
|
||||||
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
||||||
|
* @copyright 2010 Chuck Hagenbuch
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||||
|
* @version CVS: $Id: mail.php 294747 2010-02-08 08:18:33Z clockwerx $
|
||||||
|
* @link http://pear.php.net/package/Mail/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* internal PHP-mail() implementation of the PEAR Mail:: interface.
|
||||||
|
* @package Mail
|
||||||
|
* @version $Revision: 294747 $
|
||||||
|
*/
|
||||||
|
class Mail_mail extends Mail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any arguments to pass to the mail() function.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $_params = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* Instantiates a new Mail_mail:: object based on the parameters
|
||||||
|
* passed in.
|
||||||
|
*
|
||||||
|
* @param array $params Extra arguments for the mail() function.
|
||||||
|
*/
|
||||||
|
function Mail_mail($params = null)
|
||||||
|
{
|
||||||
|
// The other mail implementations accept parameters as arrays.
|
||||||
|
// In the interest of being consistent, explode an array into
|
||||||
|
// a string of parameter arguments.
|
||||||
|
if (is_array($params)) {
|
||||||
|
$this->_params = join(' ', $params);
|
||||||
|
} else {
|
||||||
|
$this->_params = $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Because the mail() function may pass headers as command
|
||||||
|
* line arguments, we can't guarantee the use of the standard
|
||||||
|
* "\r\n" separator. Instead, we use the system's native line
|
||||||
|
* separator. */
|
||||||
|
if (defined('PHP_EOL')) {
|
||||||
|
$this->sep = PHP_EOL;
|
||||||
|
} else {
|
||||||
|
$this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Mail_mail::send() function using php's built-in mail()
|
||||||
|
* command.
|
||||||
|
*
|
||||||
|
* @param mixed $recipients Either a comma-seperated list of recipients
|
||||||
|
* (RFC822 compliant), or an array of recipients,
|
||||||
|
* each RFC822 valid. This may contain recipients not
|
||||||
|
* specified in the headers, for Bcc:, resending
|
||||||
|
* messages, etc.
|
||||||
|
*
|
||||||
|
* @param array $headers The array of headers to send with the mail, in an
|
||||||
|
* associative array, where the array key is the
|
||||||
|
* header name (ie, 'Subject'), and the array value
|
||||||
|
* is the header value (ie, 'test'). The header
|
||||||
|
* produced from those values would be 'Subject:
|
||||||
|
* test'.
|
||||||
|
*
|
||||||
|
* @param string $body The full text of the message body, including any
|
||||||
|
* Mime parts, etc.
|
||||||
|
*
|
||||||
|
* @return mixed Returns true on success, or a PEAR_Error
|
||||||
|
* containing a descriptive error message on
|
||||||
|
* failure.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function send($recipients, $headers, $body)
|
||||||
|
{
|
||||||
|
if (!is_array($headers)) {
|
||||||
|
return PEAR::raiseError('$headers must be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->_sanitizeHeaders($headers);
|
||||||
|
if (is_a($result, 'PEAR_Error')) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're passed an array of recipients, implode it.
|
||||||
|
if (is_array($recipients)) {
|
||||||
|
$recipients = implode(', ', $recipients);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Subject out of the headers array so that we can
|
||||||
|
// pass it as a seperate argument to mail().
|
||||||
|
$subject = '';
|
||||||
|
if (isset($headers['Subject'])) {
|
||||||
|
$subject = $headers['Subject'];
|
||||||
|
unset($headers['Subject']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also remove the To: header. The mail() function will add its own
|
||||||
|
// To: header based on the contents of $recipients.
|
||||||
|
unset($headers['To']);
|
||||||
|
|
||||||
|
// Flatten the headers out.
|
||||||
|
$headerElements = $this->prepareHeaders($headers);
|
||||||
|
if (is_a($headerElements, 'PEAR_Error')) {
|
||||||
|
return $headerElements;
|
||||||
|
}
|
||||||
|
list(, $text_headers) = $headerElements;
|
||||||
|
|
||||||
|
// We only use mail()'s optional fifth parameter if the additional
|
||||||
|
// parameters have been provided and we're not running in safe mode.
|
||||||
|
if (empty($this->_params) || ini_get('safe_mode')) {
|
||||||
|
$result = mail($recipients, $subject, $body, $text_headers);
|
||||||
|
} else {
|
||||||
|
$result = mail($recipients, $subject, $body, $text_headers,
|
||||||
|
$this->_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the mail() function returned failure, we need to create a
|
||||||
|
// PEAR_Error object and return it instead of the boolean result.
|
||||||
|
if ($result === false) {
|
||||||
|
$result = PEAR::raiseError('mail() returned failure');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
143
core/lib/Mail/mock.php
Normal file
143
core/lib/Mail/mock.php
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Mock implementation
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* LICENSE:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Chuck Hagenbuch
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* o Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* o Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* o The names of the authors may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @category Mail
|
||||||
|
* @package Mail
|
||||||
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
||||||
|
* @copyright 2010 Chuck Hagenbuch
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||||
|
* @version CVS: $Id: mock.php 294747 2010-02-08 08:18:33Z clockwerx $
|
||||||
|
* @link http://pear.php.net/package/Mail/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock implementation of the PEAR Mail:: interface for testing.
|
||||||
|
* @access public
|
||||||
|
* @package Mail
|
||||||
|
* @version $Revision: 294747 $
|
||||||
|
*/
|
||||||
|
class Mail_mock extends Mail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of messages that have been sent with the mock.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $sentMessages = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback before sending mail.
|
||||||
|
*
|
||||||
|
* @var callback
|
||||||
|
*/
|
||||||
|
var $_preSendCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback after sending mai.
|
||||||
|
*
|
||||||
|
* @var callback
|
||||||
|
*/
|
||||||
|
var $_postSendCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* Instantiates a new Mail_mock:: object based on the parameters
|
||||||
|
* passed in. It looks for the following parameters, both optional:
|
||||||
|
* preSendCallback Called before an email would be sent.
|
||||||
|
* postSendCallback Called after an email would have been sent.
|
||||||
|
*
|
||||||
|
* @param array Hash containing any parameters.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Mail_mock($params)
|
||||||
|
{
|
||||||
|
if (isset($params['preSendCallback']) &&
|
||||||
|
is_callable($params['preSendCallback'])) {
|
||||||
|
$this->_preSendCallback = $params['preSendCallback'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($params['postSendCallback']) &&
|
||||||
|
is_callable($params['postSendCallback'])) {
|
||||||
|
$this->_postSendCallback = $params['postSendCallback'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Mail_mock::send() function. Silently discards all
|
||||||
|
* mail.
|
||||||
|
*
|
||||||
|
* @param mixed $recipients Either a comma-seperated list of recipients
|
||||||
|
* (RFC822 compliant), or an array of recipients,
|
||||||
|
* each RFC822 valid. This may contain recipients not
|
||||||
|
* specified in the headers, for Bcc:, resending
|
||||||
|
* messages, etc.
|
||||||
|
*
|
||||||
|
* @param array $headers The array of headers to send with the mail, in an
|
||||||
|
* associative array, where the array key is the
|
||||||
|
* header name (ie, 'Subject'), and the array value
|
||||||
|
* is the header value (ie, 'test'). The header
|
||||||
|
* produced from those values would be 'Subject:
|
||||||
|
* test'.
|
||||||
|
*
|
||||||
|
* @param string $body The full text of the message body, including any
|
||||||
|
* Mime parts, etc.
|
||||||
|
*
|
||||||
|
* @return mixed Returns true on success, or a PEAR_Error
|
||||||
|
* containing a descriptive error message on
|
||||||
|
* failure.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function send($recipients, $headers, $body)
|
||||||
|
{
|
||||||
|
if ($this->_preSendCallback) {
|
||||||
|
call_user_func_array($this->_preSendCallback,
|
||||||
|
array(&$this, $recipients, $headers, $body));
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body);
|
||||||
|
$this->sentMessages[] = $entry;
|
||||||
|
|
||||||
|
if ($this->_postSendCallback) {
|
||||||
|
call_user_func_array($this->_postSendCallback,
|
||||||
|
array(&$this, $recipients, $headers, $body));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
84
core/lib/Mail/null.php
Normal file
84
core/lib/Mail/null.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Null implementation of the PEAR Mail interface
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* LICENSE:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Phil Kernick
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* o Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* o Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* o The names of the authors may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @category Mail
|
||||||
|
* @package Mail
|
||||||
|
* @author Phil Kernick <philk@rotfl.com.au>
|
||||||
|
* @copyright 2010 Phil Kernick
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||||
|
* @version CVS: $Id: null.php 294747 2010-02-08 08:18:33Z clockwerx $
|
||||||
|
* @link http://pear.php.net/package/Mail/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null implementation of the PEAR Mail:: interface.
|
||||||
|
* @access public
|
||||||
|
* @package Mail
|
||||||
|
* @version $Revision: 294747 $
|
||||||
|
*/
|
||||||
|
class Mail_null extends Mail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Mail_null::send() function. Silently discards all
|
||||||
|
* mail.
|
||||||
|
*
|
||||||
|
* @param mixed $recipients Either a comma-seperated list of recipients
|
||||||
|
* (RFC822 compliant), or an array of recipients,
|
||||||
|
* each RFC822 valid. This may contain recipients not
|
||||||
|
* specified in the headers, for Bcc:, resending
|
||||||
|
* messages, etc.
|
||||||
|
*
|
||||||
|
* @param array $headers The array of headers to send with the mail, in an
|
||||||
|
* associative array, where the array key is the
|
||||||
|
* header name (ie, 'Subject'), and the array value
|
||||||
|
* is the header value (ie, 'test'). The header
|
||||||
|
* produced from those values would be 'Subject:
|
||||||
|
* test'.
|
||||||
|
*
|
||||||
|
* @param string $body The full text of the message body, including any
|
||||||
|
* Mime parts, etc.
|
||||||
|
*
|
||||||
|
* @return mixed Returns true on success, or a PEAR_Error
|
||||||
|
* containing a descriptive error message on
|
||||||
|
* failure.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function send($recipients, $headers, $body)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
171
core/lib/Mail/sendmail.php
Normal file
171
core/lib/Mail/sendmail.php
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<?php
|
||||||
|
//
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | PHP Version 4 |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | Copyright (c) 1997-2003 The PHP Group |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | This source file is subject to version 2.02 of the PHP license, |
|
||||||
|
// | that is bundled with this package in the file LICENSE, and is |
|
||||||
|
// | available at through the world-wide-web at |
|
||||||
|
// | http://www.php.net/license/2_02.txt. |
|
||||||
|
// | If you did not receive a copy of the PHP license and are unable to |
|
||||||
|
// | obtain it through the world-wide-web, please send a note to |
|
||||||
|
// | license@php.net so we can mail you a copy immediately. |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
// | Author: Chuck Hagenbuch <chuck@horde.org> |
|
||||||
|
// +----------------------------------------------------------------------+
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sendmail implementation of the PEAR Mail:: interface.
|
||||||
|
* @access public
|
||||||
|
* @package Mail
|
||||||
|
* @version $Revision: 294744 $
|
||||||
|
*/
|
||||||
|
class Mail_sendmail extends Mail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location of the sendmail or sendmail wrapper binary on the
|
||||||
|
* filesystem.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $sendmail_path = '/usr/sbin/sendmail';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any extra command-line parameters to pass to the sendmail or
|
||||||
|
* sendmail wrapper binary.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $sendmail_args = '-i';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* Instantiates a new Mail_sendmail:: object based on the parameters
|
||||||
|
* passed in. It looks for the following parameters:
|
||||||
|
* sendmail_path The location of the sendmail binary on the
|
||||||
|
* filesystem. Defaults to '/usr/sbin/sendmail'.
|
||||||
|
*
|
||||||
|
* sendmail_args Any extra parameters to pass to the sendmail
|
||||||
|
* or sendmail wrapper binary.
|
||||||
|
*
|
||||||
|
* If a parameter is present in the $params array, it replaces the
|
||||||
|
* default.
|
||||||
|
*
|
||||||
|
* @param array $params Hash containing any parameters different from the
|
||||||
|
* defaults.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Mail_sendmail($params)
|
||||||
|
{
|
||||||
|
if (isset($params['sendmail_path'])) {
|
||||||
|
$this->sendmail_path = $params['sendmail_path'];
|
||||||
|
}
|
||||||
|
if (isset($params['sendmail_args'])) {
|
||||||
|
$this->sendmail_args = $params['sendmail_args'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because we need to pass message headers to the sendmail program on
|
||||||
|
* the commandline, we can't guarantee the use of the standard "\r\n"
|
||||||
|
* separator. Instead, we use the system's native line separator.
|
||||||
|
*/
|
||||||
|
if (defined('PHP_EOL')) {
|
||||||
|
$this->sep = PHP_EOL;
|
||||||
|
} else {
|
||||||
|
$this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Mail::send() function using the sendmail
|
||||||
|
* command-line binary.
|
||||||
|
*
|
||||||
|
* @param mixed $recipients Either a comma-seperated list of recipients
|
||||||
|
* (RFC822 compliant), or an array of recipients,
|
||||||
|
* each RFC822 valid. This may contain recipients not
|
||||||
|
* specified in the headers, for Bcc:, resending
|
||||||
|
* messages, etc.
|
||||||
|
*
|
||||||
|
* @param array $headers The array of headers to send with the mail, in an
|
||||||
|
* associative array, where the array key is the
|
||||||
|
* header name (ie, 'Subject'), and the array value
|
||||||
|
* is the header value (ie, 'test'). The header
|
||||||
|
* produced from those values would be 'Subject:
|
||||||
|
* test'.
|
||||||
|
*
|
||||||
|
* @param string $body The full text of the message body, including any
|
||||||
|
* Mime parts, etc.
|
||||||
|
*
|
||||||
|
* @return mixed Returns true on success, or a PEAR_Error
|
||||||
|
* containing a descriptive error message on
|
||||||
|
* failure.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function send($recipients, $headers, $body)
|
||||||
|
{
|
||||||
|
if (!is_array($headers)) {
|
||||||
|
return PEAR::raiseError('$headers must be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->_sanitizeHeaders($headers);
|
||||||
|
if (is_a($result, 'PEAR_Error')) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$recipients = $this->parseRecipients($recipients);
|
||||||
|
if (is_a($recipients, 'PEAR_Error')) {
|
||||||
|
return $recipients;
|
||||||
|
}
|
||||||
|
$recipients = implode(' ', array_map('escapeshellarg', $recipients));
|
||||||
|
|
||||||
|
$headerElements = $this->prepareHeaders($headers);
|
||||||
|
if (is_a($headerElements, 'PEAR_Error')) {
|
||||||
|
return $headerElements;
|
||||||
|
}
|
||||||
|
list($from, $text_headers) = $headerElements;
|
||||||
|
|
||||||
|
/* Since few MTAs are going to allow this header to be forged
|
||||||
|
* unless it's in the MAIL FROM: exchange, we'll use
|
||||||
|
* Return-Path instead of From: if it's set. */
|
||||||
|
if (!empty($headers['Return-Path'])) {
|
||||||
|
$from = $headers['Return-Path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($from)) {
|
||||||
|
return PEAR::raiseError('No from address given.');
|
||||||
|
} elseif (strpos($from, ' ') !== false ||
|
||||||
|
strpos($from, ';') !== false ||
|
||||||
|
strpos($from, '&') !== false ||
|
||||||
|
strpos($from, '`') !== false) {
|
||||||
|
return PEAR::raiseError('From address specified with dangerous characters.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$from = escapeshellarg($from); // Security bug #16200
|
||||||
|
|
||||||
|
$mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w');
|
||||||
|
if (!$mail) {
|
||||||
|
return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the headers following by two newlines: one to end the headers
|
||||||
|
// section and a second to separate the headers block from the body.
|
||||||
|
fputs($mail, $text_headers . $this->sep . $this->sep);
|
||||||
|
|
||||||
|
fputs($mail, $body);
|
||||||
|
$result = pclose($mail);
|
||||||
|
if (version_compare(phpversion(), '4.2.3') == -1) {
|
||||||
|
// With older php versions, we need to shift the pclose
|
||||||
|
// result to get the exit code.
|
||||||
|
$result = $result >> 8 & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result != 0) {
|
||||||
|
return PEAR::raiseError('sendmail returned error code ' . $result,
|
||||||
|
$result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
444
core/lib/Mail/smtp.php
Normal file
444
core/lib/Mail/smtp.php
Normal file
@@ -0,0 +1,444 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* LICENSE:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Chuck Hagenbuch
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* o Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* o Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* o The names of the authors may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @category HTTP
|
||||||
|
* @package HTTP_Request
|
||||||
|
* @author Jon Parise <jon@php.net>
|
||||||
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
||||||
|
* @copyright 2010 Chuck Hagenbuch
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||||
|
* @version CVS: $Id: smtp.php 294747 2010-02-08 08:18:33Z clockwerx $
|
||||||
|
* @link http://pear.php.net/package/Mail/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Error: Failed to create a Net_SMTP object */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
|
||||||
|
|
||||||
|
/** Error: Failed to connect to SMTP server */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
|
||||||
|
|
||||||
|
/** Error: SMTP authentication failure */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
|
||||||
|
|
||||||
|
/** Error: No From: address has been provided */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
|
||||||
|
|
||||||
|
/** Error: Failed to set sender */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
|
||||||
|
|
||||||
|
/** Error: Failed to add recipient */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
|
||||||
|
|
||||||
|
/** Error: Failed to send data */
|
||||||
|
define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
|
||||||
|
* @access public
|
||||||
|
* @package Mail
|
||||||
|
* @version $Revision: 294747 $
|
||||||
|
*/
|
||||||
|
class Mail_smtp extends Mail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP connection object.
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $_smtp = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of service extension parameters to pass to the Net_SMTP
|
||||||
|
* mailFrom() command.
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
var $_extparams = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SMTP host to connect to.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $host = 'localhost';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port the SMTP server is on.
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
var $port = 25;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should SMTP authentication be used?
|
||||||
|
*
|
||||||
|
* This value may be set to true, false or the name of a specific
|
||||||
|
* authentication method.
|
||||||
|
*
|
||||||
|
* If the value is set to true, the Net_SMTP package will attempt to use
|
||||||
|
* the best authentication method advertised by the remote SMTP server.
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
var $auth = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username to use if the SMTP server requires authentication.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $username = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The password to use if the SMTP server requires authentication.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $password = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hostname or domain that will be sent to the remote SMTP server in the
|
||||||
|
* HELO / EHLO message.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
var $localhost = 'localhost';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP connection timeout value. NULL indicates no timeout.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
var $timeout = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on Net_SMTP debugging?
|
||||||
|
*
|
||||||
|
* @var boolean $debug
|
||||||
|
*/
|
||||||
|
var $debug = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not the SMTP connection should persist over
|
||||||
|
* multiple calls to the send() method.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
var $persist = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use SMTP command pipelining (specified in RFC 2920) if the SMTP server
|
||||||
|
* supports it. This speeds up delivery over high-latency connections. By
|
||||||
|
* default, use the default value supplied by Net_SMTP.
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
var $pipelining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* Instantiates a new Mail_smtp:: object based on the parameters
|
||||||
|
* passed in. It looks for the following parameters:
|
||||||
|
* host The server to connect to. Defaults to localhost.
|
||||||
|
* port The port to connect to. Defaults to 25.
|
||||||
|
* auth SMTP authentication. Defaults to none.
|
||||||
|
* username The username to use for SMTP auth. No default.
|
||||||
|
* password The password to use for SMTP auth. No default.
|
||||||
|
* localhost The local hostname / domain. Defaults to localhost.
|
||||||
|
* timeout The SMTP connection timeout. Defaults to none.
|
||||||
|
* verp Whether to use VERP or not. Defaults to false.
|
||||||
|
* DEPRECATED as of 1.2.0 (use setMailParams()).
|
||||||
|
* debug Activate SMTP debug mode? Defaults to false.
|
||||||
|
* persist Should the SMTP connection persist?
|
||||||
|
* pipelining Use SMTP command pipelining
|
||||||
|
*
|
||||||
|
* If a parameter is present in the $params array, it replaces the
|
||||||
|
* default.
|
||||||
|
*
|
||||||
|
* @param array Hash containing any parameters different from the
|
||||||
|
* defaults.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function Mail_smtp($params)
|
||||||
|
{
|
||||||
|
if (isset($params['host'])) $this->host = $params['host'];
|
||||||
|
if (isset($params['port'])) $this->port = $params['port'];
|
||||||
|
if (isset($params['auth'])) $this->auth = $params['auth'];
|
||||||
|
if (isset($params['username'])) $this->username = $params['username'];
|
||||||
|
if (isset($params['password'])) $this->password = $params['password'];
|
||||||
|
if (isset($params['localhost'])) $this->localhost = $params['localhost'];
|
||||||
|
if (isset($params['timeout'])) $this->timeout = $params['timeout'];
|
||||||
|
if (isset($params['debug'])) $this->debug = (bool)$params['debug'];
|
||||||
|
if (isset($params['persist'])) $this->persist = (bool)$params['persist'];
|
||||||
|
if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining'];
|
||||||
|
|
||||||
|
// Deprecated options
|
||||||
|
if (isset($params['verp'])) {
|
||||||
|
$this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']);
|
||||||
|
}
|
||||||
|
|
||||||
|
register_shutdown_function(array(&$this, '_Mail_smtp'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor implementation to ensure that we disconnect from any
|
||||||
|
* potentially-alive persistent SMTP connections.
|
||||||
|
*/
|
||||||
|
function _Mail_smtp()
|
||||||
|
{
|
||||||
|
$this->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Mail::send() function using SMTP.
|
||||||
|
*
|
||||||
|
* @param mixed $recipients Either a comma-seperated list of recipients
|
||||||
|
* (RFC822 compliant), or an array of recipients,
|
||||||
|
* each RFC822 valid. This may contain recipients not
|
||||||
|
* specified in the headers, for Bcc:, resending
|
||||||
|
* messages, etc.
|
||||||
|
*
|
||||||
|
* @param array $headers The array of headers to send with the mail, in an
|
||||||
|
* associative array, where the array key is the
|
||||||
|
* header name (e.g., 'Subject'), and the array value
|
||||||
|
* is the header value (e.g., 'test'). The header
|
||||||
|
* produced from those values would be 'Subject:
|
||||||
|
* test'.
|
||||||
|
*
|
||||||
|
* @param string $body The full text of the message body, including any
|
||||||
|
* MIME parts, etc.
|
||||||
|
*
|
||||||
|
* @return mixed Returns true on success, or a PEAR_Error
|
||||||
|
* containing a descriptive error message on
|
||||||
|
* failure.
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function send($recipients, $headers, $body)
|
||||||
|
{
|
||||||
|
/* If we don't already have an SMTP object, create one. */
|
||||||
|
$result = &$this->getSMTPObject();
|
||||||
|
if (PEAR::isError($result)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($headers)) {
|
||||||
|
return PEAR::raiseError('$headers must be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_sanitizeHeaders($headers);
|
||||||
|
|
||||||
|
$headerElements = $this->prepareHeaders($headers);
|
||||||
|
if (is_a($headerElements, 'PEAR_Error')) {
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return $headerElements;
|
||||||
|
}
|
||||||
|
list($from, $textHeaders) = $headerElements;
|
||||||
|
|
||||||
|
/* Since few MTAs are going to allow this header to be forged
|
||||||
|
* unless it's in the MAIL FROM: exchange, we'll use
|
||||||
|
* Return-Path instead of From: if it's set. */
|
||||||
|
if (!empty($headers['Return-Path'])) {
|
||||||
|
$from = $headers['Return-Path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($from)) {
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return PEAR::raiseError('No From: address has been provided',
|
||||||
|
PEAR_MAIL_SMTP_ERROR_FROM);
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = null;
|
||||||
|
if (!empty($this->_extparams)) {
|
||||||
|
foreach ($this->_extparams as $key => $val) {
|
||||||
|
$params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) {
|
||||||
|
$error = $this->_error("Failed to set sender: $from", $res);
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
$recipients = $this->parseRecipients($recipients);
|
||||||
|
if (is_a($recipients, 'PEAR_Error')) {
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return $recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($recipients as $recipient) {
|
||||||
|
$res = $this->_smtp->rcptTo($recipient);
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$error = $this->_error("Failed to add recipient: $recipient", $res);
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the message's headers and the body as SMTP data. */
|
||||||
|
$res = $this->_smtp->data($textHeaders . "\r\n\r\n" . $body);
|
||||||
|
list(,$args) = $this->_smtp->getResponse();
|
||||||
|
|
||||||
|
if (preg_match("/Ok: queued as (.*)/", $args, $queued)) {
|
||||||
|
$this->queued_as = $queued[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to.
|
||||||
|
* ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */
|
||||||
|
$this->greeting = $this->_smtp->getGreeting();
|
||||||
|
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$error = $this->_error('Failed to send data', $res);
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If persistent connections are disabled, destroy our SMTP object. */
|
||||||
|
if ($this->persist === false) {
|
||||||
|
$this->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to the SMTP server by instantiating a Net_SMTP object.
|
||||||
|
*
|
||||||
|
* @return mixed Returns a reference to the Net_SMTP object on success, or
|
||||||
|
* a PEAR_Error containing a descriptive error message on
|
||||||
|
* failure.
|
||||||
|
*
|
||||||
|
* @since 1.2.0
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function &getSMTPObject()
|
||||||
|
{
|
||||||
|
if (is_object($this->_smtp) !== false) {
|
||||||
|
return $this->_smtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
include_once 'Net/SMTP.php';
|
||||||
|
$this->_smtp = &new Net_SMTP($this->host,
|
||||||
|
$this->port,
|
||||||
|
$this->localhost);
|
||||||
|
|
||||||
|
/* If we still don't have an SMTP object at this point, fail. */
|
||||||
|
if (is_object($this->_smtp) === false) {
|
||||||
|
return PEAR::raiseError('Failed to create a Net_SMTP object',
|
||||||
|
PEAR_MAIL_SMTP_ERROR_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the SMTP connection. */
|
||||||
|
if ($this->debug) {
|
||||||
|
$this->_smtp->setDebug(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to connect to the configured SMTP server. */
|
||||||
|
if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
|
||||||
|
$error = $this->_error('Failed to connect to ' .
|
||||||
|
$this->host . ':' . $this->port,
|
||||||
|
$res);
|
||||||
|
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to authenticate if authentication has been enabled. */
|
||||||
|
if ($this->auth) {
|
||||||
|
$method = is_string($this->auth) ? $this->auth : '';
|
||||||
|
|
||||||
|
if (PEAR::isError($res = $this->_smtp->auth($this->username,
|
||||||
|
$this->password,
|
||||||
|
$method))) {
|
||||||
|
$error = $this->_error("$method authentication failure",
|
||||||
|
$res);
|
||||||
|
$this->_smtp->rset();
|
||||||
|
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_smtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add parameter associated with a SMTP service extension.
|
||||||
|
*
|
||||||
|
* @param string Extension keyword.
|
||||||
|
* @param string Any value the keyword needs.
|
||||||
|
*
|
||||||
|
* @since 1.2.0
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function addServiceExtensionParameter($keyword, $value = null)
|
||||||
|
{
|
||||||
|
$this->_extparams[$keyword] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect and destroy the current SMTP connection.
|
||||||
|
*
|
||||||
|
* @return boolean True if the SMTP connection no longer exists.
|
||||||
|
*
|
||||||
|
* @since 1.1.9
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function disconnect()
|
||||||
|
{
|
||||||
|
/* If we have an SMTP object, disconnect and destroy it. */
|
||||||
|
if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
|
||||||
|
$this->_smtp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are disconnected if we no longer have an SMTP object. */
|
||||||
|
return ($this->_smtp === null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a standardized string describing the current SMTP error.
|
||||||
|
*
|
||||||
|
* @param string $text Custom string describing the error context.
|
||||||
|
* @param object $error Reference to the current PEAR_Error object.
|
||||||
|
*
|
||||||
|
* @return string A string describing the current SMTP error.
|
||||||
|
*
|
||||||
|
* @since 1.1.7
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _error($text, &$error)
|
||||||
|
{
|
||||||
|
/* Split the SMTP response into a code and a response string. */
|
||||||
|
list($code, $response) = $this->_smtp->getResponse();
|
||||||
|
|
||||||
|
/* Build our standardized error string. */
|
||||||
|
return $text
|
||||||
|
. ' [SMTP: ' . $error->getMessage()
|
||||||
|
. " (code: $code, response: $response)]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
502
core/lib/Mail/smtpmx.php
Normal file
502
core/lib/Mail/smtpmx.php
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
<?PHP
|
||||||
|
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP MX
|
||||||
|
*
|
||||||
|
* SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* LICENSE:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, gERD Schaufelberger
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* o Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* o Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* o The names of the authors may not be used to endorse or promote
|
||||||
|
* products derived from this software without specific prior written
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @category Mail
|
||||||
|
* @package Mail_smtpmx
|
||||||
|
* @author gERD Schaufelberger <gerd@php-tools.net>
|
||||||
|
* @copyright 2010 gERD Schaufelberger
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||||
|
* @version CVS: $Id: smtpmx.php 294747 2010-02-08 08:18:33Z clockwerx $
|
||||||
|
* @link http://pear.php.net/package/Mail/
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'Net/SMTP.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @author gERD Schaufelberger <gerd@php-tools.net>
|
||||||
|
* @package Mail
|
||||||
|
* @version $Revision: 294747 $
|
||||||
|
*/
|
||||||
|
class Mail_smtpmx extends Mail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP connection object.
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
var $_smtp = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port the SMTP server is on.
|
||||||
|
* @var integer
|
||||||
|
* @see getservicebyname()
|
||||||
|
*/
|
||||||
|
var $port = 25;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hostname or domain that will be sent to the remote SMTP server in the
|
||||||
|
* HELO / EHLO message.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @see posix_uname()
|
||||||
|
*/
|
||||||
|
var $mailname = 'localhost';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP connection timeout value. NULL indicates no timeout.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
var $timeout = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* use either PEAR:Net_DNS or getmxrr
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
var $withNetDns = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PEAR:Net_DNS_Resolver
|
||||||
|
*
|
||||||
|
* @var object
|
||||||
|
*/
|
||||||
|
var $resolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to use VERP or not. If not a boolean, the string value
|
||||||
|
* will be used as the VERP separators.
|
||||||
|
*
|
||||||
|
* @var mixed boolean or string
|
||||||
|
*/
|
||||||
|
var $verp = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to use VRFY or not.
|
||||||
|
*
|
||||||
|
* @var boolean $vrfy
|
||||||
|
*/
|
||||||
|
var $vrfy = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to test mode - don't send emails for real
|
||||||
|
*
|
||||||
|
* @var boolean $debug
|
||||||
|
*/
|
||||||
|
var $test = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on Net_SMTP debugging?
|
||||||
|
*
|
||||||
|
* @var boolean $peardebug
|
||||||
|
*/
|
||||||
|
var $debug = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* internal error codes
|
||||||
|
*
|
||||||
|
* translate internal error identifier to PEAR-Error codes and human
|
||||||
|
* readable messages.
|
||||||
|
*
|
||||||
|
* @var boolean $debug
|
||||||
|
* @todo as I need unique error-codes to identify what exactly went wrond
|
||||||
|
* I did not use intergers as it should be. Instead I added a "namespace"
|
||||||
|
* for each code. This avoids conflicts with error codes from different
|
||||||
|
* classes. How can I use unique error codes and stay conform with PEAR?
|
||||||
|
*/
|
||||||
|
var $errorCode = array(
|
||||||
|
'not_connected' => array(
|
||||||
|
'code' => 1,
|
||||||
|
'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
|
||||||
|
),
|
||||||
|
'failed_vrfy_rcpt' => array(
|
||||||
|
'code' => 2,
|
||||||
|
'msg' => 'Recipient "{RCPT}" could not be veryfied.'
|
||||||
|
),
|
||||||
|
'failed_set_from' => array(
|
||||||
|
'code' => 3,
|
||||||
|
'msg' => 'Failed to set sender: {FROM}.'
|
||||||
|
),
|
||||||
|
'failed_set_rcpt' => array(
|
||||||
|
'code' => 4,
|
||||||
|
'msg' => 'Failed to set recipient: {RCPT}.'
|
||||||
|
),
|
||||||
|
'failed_send_data' => array(
|
||||||
|
'code' => 5,
|
||||||
|
'msg' => 'Failed to send mail to: {RCPT}.'
|
||||||
|
),
|
||||||
|
'no_from' => array(
|
||||||
|
'code' => 5,
|
||||||
|
'msg' => 'No from address has be provided.'
|
||||||
|
),
|
||||||
|
'send_data' => array(
|
||||||
|
'code' => 7,
|
||||||
|
'msg' => 'Failed to create Net_SMTP object.'
|
||||||
|
),
|
||||||
|
'no_mx' => array(
|
||||||
|
'code' => 8,
|
||||||
|
'msg' => 'No MX-record for {RCPT} found.'
|
||||||
|
),
|
||||||
|
'no_resolver' => array(
|
||||||
|
'code' => 9,
|
||||||
|
'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
|
||||||
|
),
|
||||||
|
'failed_rset' => array(
|
||||||
|
'code' => 10,
|
||||||
|
'msg' => 'RSET command failed, SMTP-connection corrupt.'
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* Instantiates a new Mail_smtp:: object based on the parameters
|
||||||
|
* passed in. It looks for the following parameters:
|
||||||
|
* mailname The name of the local mail system (a valid hostname which matches the reverse lookup)
|
||||||
|
* port smtp-port - the default comes from getservicebyname() and should work fine
|
||||||
|
* timeout The SMTP connection timeout. Defaults to 30 seconds.
|
||||||
|
* vrfy Whether to use VRFY or not. Defaults to false.
|
||||||
|
* verp Whether to use VERP or not. Defaults to false.
|
||||||
|
* test Activate test mode? Defaults to false.
|
||||||
|
* debug Activate SMTP and Net_DNS debug mode? Defaults to false.
|
||||||
|
* netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true
|
||||||
|
*
|
||||||
|
* If a parameter is present in the $params array, it replaces the
|
||||||
|
* default.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array Hash containing any parameters different from the
|
||||||
|
* defaults.
|
||||||
|
* @see _Mail_smtpmx()
|
||||||
|
*/
|
||||||
|
function __construct($params)
|
||||||
|
{
|
||||||
|
if (isset($params['mailname'])) {
|
||||||
|
$this->mailname = $params['mailname'];
|
||||||
|
} else {
|
||||||
|
// try to find a valid mailname
|
||||||
|
if (function_exists('posix_uname')) {
|
||||||
|
$uname = posix_uname();
|
||||||
|
$this->mailname = $uname['nodename'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// port number
|
||||||
|
if (isset($params['port'])) {
|
||||||
|
$this->_port = $params['port'];
|
||||||
|
} else {
|
||||||
|
$this->_port = getservbyname('smtp', 'tcp');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($params['timeout'])) $this->timeout = $params['timeout'];
|
||||||
|
if (isset($params['verp'])) $this->verp = $params['verp'];
|
||||||
|
if (isset($params['test'])) $this->test = $params['test'];
|
||||||
|
if (isset($params['peardebug'])) $this->test = $params['peardebug'];
|
||||||
|
if (isset($params['netdns'])) $this->withNetDns = $params['netdns'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor wrapper for PHP4
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array Hash containing any parameters different from the defaults
|
||||||
|
* @see __construct()
|
||||||
|
*/
|
||||||
|
function Mail_smtpmx($params)
|
||||||
|
{
|
||||||
|
$this->__construct($params);
|
||||||
|
register_shutdown_function(array(&$this, '__destruct'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor implementation to ensure that we disconnect from any
|
||||||
|
* potentially-alive persistent SMTP connections.
|
||||||
|
*/
|
||||||
|
function __destruct()
|
||||||
|
{
|
||||||
|
if (is_object($this->_smtp)) {
|
||||||
|
$this->_smtp->disconnect();
|
||||||
|
$this->_smtp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Mail::send() function using SMTP direct delivery
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param mixed $recipients in RFC822 style or array
|
||||||
|
* @param array $headers The array of headers to send with the mail.
|
||||||
|
* @param string $body The full text of the message body,
|
||||||
|
* @return mixed Returns true on success, or a PEAR_Error
|
||||||
|
*/
|
||||||
|
function send($recipients, $headers, $body)
|
||||||
|
{
|
||||||
|
if (!is_array($headers)) {
|
||||||
|
return PEAR::raiseError('$headers must be an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->_sanitizeHeaders($headers);
|
||||||
|
if (is_a($result, 'PEAR_Error')) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare headers
|
||||||
|
$headerElements = $this->prepareHeaders($headers);
|
||||||
|
if (is_a($headerElements, 'PEAR_Error')) {
|
||||||
|
return $headerElements;
|
||||||
|
}
|
||||||
|
list($from, $textHeaders) = $headerElements;
|
||||||
|
|
||||||
|
// use 'Return-Path' if possible
|
||||||
|
if (!empty($headers['Return-Path'])) {
|
||||||
|
$from = $headers['Return-Path'];
|
||||||
|
}
|
||||||
|
if (!isset($from)) {
|
||||||
|
return $this->_raiseError('no_from');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare recipients
|
||||||
|
$recipients = $this->parseRecipients($recipients);
|
||||||
|
if (is_a($recipients, 'PEAR_Error')) {
|
||||||
|
return $recipients;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($recipients as $rcpt) {
|
||||||
|
list($user, $host) = explode('@', $rcpt);
|
||||||
|
|
||||||
|
$mx = $this->_getMx($host);
|
||||||
|
if (is_a($mx, 'PEAR_Error')) {
|
||||||
|
return $mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($mx)) {
|
||||||
|
$info = array('rcpt' => $rcpt);
|
||||||
|
return $this->_raiseError('no_mx', $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
$connected = false;
|
||||||
|
foreach ($mx as $mserver => $mpriority) {
|
||||||
|
$this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname);
|
||||||
|
|
||||||
|
// configure the SMTP connection.
|
||||||
|
if ($this->debug) {
|
||||||
|
$this->_smtp->setDebug(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to connect to the configured SMTP server.
|
||||||
|
$res = $this->_smtp->connect($this->timeout);
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$this->_smtp = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// connection established
|
||||||
|
if ($res) {
|
||||||
|
$connected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$connected) {
|
||||||
|
$info = array(
|
||||||
|
'host' => implode(', ', array_keys($mx)),
|
||||||
|
'port' => $this->port,
|
||||||
|
'rcpt' => $rcpt,
|
||||||
|
);
|
||||||
|
return $this->_raiseError('not_connected', $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify recipient
|
||||||
|
if ($this->vrfy) {
|
||||||
|
$res = $this->_smtp->vrfy($rcpt);
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$info = array('rcpt' => $rcpt);
|
||||||
|
return $this->_raiseError('failed_vrfy_rcpt', $info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mail from:
|
||||||
|
$args['verp'] = $this->verp;
|
||||||
|
$res = $this->_smtp->mailFrom($from, $args);
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$info = array('from' => $from);
|
||||||
|
return $this->_raiseError('failed_set_from', $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rcpt to:
|
||||||
|
$res = $this->_smtp->rcptTo($rcpt);
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$info = array('rcpt' => $rcpt);
|
||||||
|
return $this->_raiseError('failed_set_rcpt', $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't send anything in test mode
|
||||||
|
if ($this->test) {
|
||||||
|
$result = $this->_smtp->rset();
|
||||||
|
$res = $this->_smtp->rset();
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
return $this->_raiseError('failed_rset');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_smtp->disconnect();
|
||||||
|
$this->_smtp = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send data
|
||||||
|
$res = $this->_smtp->data("$textHeaders\r\n$body");
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
$info = array('rcpt' => $rcpt);
|
||||||
|
return $this->_raiseError('failed_send_data', $info);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_smtp->disconnect();
|
||||||
|
$this->_smtp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recieve mx rexords for a spciefied host
|
||||||
|
*
|
||||||
|
* The MX records
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $host mail host
|
||||||
|
* @return mixed sorted
|
||||||
|
*/
|
||||||
|
function _getMx($host)
|
||||||
|
{
|
||||||
|
$mx = array();
|
||||||
|
|
||||||
|
if ($this->withNetDns) {
|
||||||
|
$res = $this->_loadNetDns();
|
||||||
|
if (is_a($res, 'PEAR_Error')) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->resolver->query($host, 'MX');
|
||||||
|
if (!$response) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($response->answer as $rr) {
|
||||||
|
if ($rr->type == 'MX') {
|
||||||
|
$mx[$rr->exchange] = $rr->preference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$mxHost = array();
|
||||||
|
$mxWeight = array();
|
||||||
|
|
||||||
|
if (!getmxrr($host, $mxHost, $mxWeight)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for ($i = 0; $i < count($mxHost); ++$i) {
|
||||||
|
$mx[$mxHost[$i]] = $mxWeight[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($mx);
|
||||||
|
return $mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize PEAR:Net_DNS_Resolver
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @return boolean true on success
|
||||||
|
*/
|
||||||
|
function _loadNetDns()
|
||||||
|
{
|
||||||
|
if (is_object($this->resolver)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!include_once 'Net/DNS.php') {
|
||||||
|
return $this->_raiseError('no_resolver');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resolver = new Net_DNS_Resolver();
|
||||||
|
if ($this->debug) {
|
||||||
|
$this->resolver->test = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raise standardized error
|
||||||
|
*
|
||||||
|
* include additional information in error message
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $id maps error ids to codes and message
|
||||||
|
* @param array $info optional information in associative array
|
||||||
|
* @see _errorCode
|
||||||
|
*/
|
||||||
|
function _raiseError($id, $info = array())
|
||||||
|
{
|
||||||
|
$code = $this->errorCode[$id]['code'];
|
||||||
|
$msg = $this->errorCode[$id]['msg'];
|
||||||
|
|
||||||
|
// include info to messages
|
||||||
|
if (!empty($info)) {
|
||||||
|
$search = array();
|
||||||
|
$replace = array();
|
||||||
|
|
||||||
|
foreach ($info as $key => $value) {
|
||||||
|
array_push($search, '{' . strtoupper($key) . '}');
|
||||||
|
array_push($replace, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = str_replace($search, $replace, $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PEAR::raiseError($msg, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,10 @@
|
|||||||
"filp/whoops": "~2.1",
|
"filp/whoops": "~2.1",
|
||||||
"swiftmailer/swiftmailer": "^6.0",
|
"swiftmailer/swiftmailer": "^6.0",
|
||||||
"pear/net_smtp": "^1.7",
|
"pear/net_smtp": "^1.7",
|
||||||
"pear/mail": "^1.4"
|
"pear/mail": "^1.4",
|
||||||
|
"spomky-labs/base64url": "^1.0",
|
||||||
|
"cebe/markdown": "^1.2",
|
||||||
|
"neitanod/forceutf8": "^2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "~6"
|
"phpunit/phpunit": "~6"
|
||||||
|
|||||||
273
core/lib/composer/composer.lock
generated
273
core/lib/composer/composer.lock
generated
@@ -4,9 +4,68 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "3a99d8f1889b03e3d3d346d1c53e284a",
|
"content-hash": "45cdd8adec569a3ef6dfed9c8b1fab41",
|
||||||
"content-hash": "0d37f31f02f0af3f426b668e57096b14",
|
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "cebe/markdown",
|
||||||
|
"version": "1.2.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cebe/markdown.git",
|
||||||
|
"reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cebe/markdown/zipball/9bac5e971dd391e2802dca5400bbeacbaea9eb86",
|
||||||
|
"reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"lib-pcre": "*",
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"cebe/indent": "*",
|
||||||
|
"facebook/xhprof": "*@dev",
|
||||||
|
"phpunit/phpunit": "4.1.*"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/markdown"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.2.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"cebe\\markdown\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Carsten Brandt",
|
||||||
|
"email": "mail@cebe.cc",
|
||||||
|
"homepage": "http://cebe.cc/",
|
||||||
|
"role": "Creator"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A super fast, highly extensible markdown parser for PHP",
|
||||||
|
"homepage": "https://github.com/cebe/markdown#readme",
|
||||||
|
"keywords": [
|
||||||
|
"extensible",
|
||||||
|
"fast",
|
||||||
|
"gfm",
|
||||||
|
"markdown",
|
||||||
|
"markdown-extra"
|
||||||
|
],
|
||||||
|
"time": "2018-03-26T11:24:36+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "consolidation/annotated-command",
|
"name": "consolidation/annotated-command",
|
||||||
"version": "2.8.2",
|
"version": "2.8.2",
|
||||||
@@ -56,7 +115,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Initialize Symfony Console commands from annotated command class methods.",
|
"description": "Initialize Symfony Console commands from annotated command class methods.",
|
||||||
"time": "2017-11-29 16:23:23"
|
"time": "2017-11-29T16:23:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "consolidation/config",
|
"name": "consolidation/config",
|
||||||
@@ -110,7 +169,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Provide configuration services for a commandline tool.",
|
"description": "Provide configuration services for a commandline tool.",
|
||||||
"time": "2017-12-22 17:28:19"
|
"time": "2017-12-22T17:28:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "consolidation/log",
|
"name": "consolidation/log",
|
||||||
@@ -158,7 +217,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.",
|
"description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.",
|
||||||
"time": "2017-11-29 01:44:16"
|
"time": "2017-11-29T01:44:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "consolidation/output-formatters",
|
"name": "consolidation/output-formatters",
|
||||||
@@ -207,7 +266,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Format text by applying transformations provided by plug-in formatters.",
|
"description": "Format text by applying transformations provided by plug-in formatters.",
|
||||||
"time": "2017-11-29 15:25:38"
|
"time": "2017-11-29T15:25:38+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "consolidation/robo",
|
"name": "consolidation/robo",
|
||||||
@@ -284,7 +343,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Modern task runner",
|
"description": "Modern task runner",
|
||||||
"time": "2017-12-29 06:48:35"
|
"time": "2017-12-29T06:48:35+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "container-interop/container-interop",
|
"name": "container-interop/container-interop",
|
||||||
@@ -315,7 +374,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||||
"homepage": "https://github.com/container-interop/container-interop",
|
"homepage": "https://github.com/container-interop/container-interop",
|
||||||
"time": "2017-02-14 19:40:03"
|
"time": "2017-02-14T19:40:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
@@ -374,7 +433,7 @@
|
|||||||
"dot",
|
"dot",
|
||||||
"notation"
|
"notation"
|
||||||
],
|
],
|
||||||
"time": "2017-01-20 21:14:22"
|
"time": "2017-01-20T21:14:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/lexer",
|
"name": "doctrine/lexer",
|
||||||
@@ -428,7 +487,7 @@
|
|||||||
"lexer",
|
"lexer",
|
||||||
"parser"
|
"parser"
|
||||||
],
|
],
|
||||||
"time": "2014-09-09 13:34:57"
|
"time": "2014-09-09T13:34:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "egulias/email-validator",
|
"name": "egulias/email-validator",
|
||||||
@@ -485,7 +544,7 @@
|
|||||||
"validation",
|
"validation",
|
||||||
"validator"
|
"validator"
|
||||||
],
|
],
|
||||||
"time": "2017-11-15 23:40:40"
|
"time": "2017-11-15T23:40:40+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "filp/whoops",
|
"name": "filp/whoops",
|
||||||
@@ -546,7 +605,7 @@
|
|||||||
"throwable",
|
"throwable",
|
||||||
"whoops"
|
"whoops"
|
||||||
],
|
],
|
||||||
"time": "2017-11-23 18:22:44"
|
"time": "2017-11-23T18:22:44+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gettext/gettext",
|
"name": "gettext/gettext",
|
||||||
@@ -606,7 +665,7 @@
|
|||||||
"po",
|
"po",
|
||||||
"translation"
|
"translation"
|
||||||
],
|
],
|
||||||
"time": "2016-06-15 18:14:14"
|
"time": "2016-06-15T18:14:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gettext/languages",
|
"name": "gettext/languages",
|
||||||
@@ -667,7 +726,7 @@
|
|||||||
"translations",
|
"translations",
|
||||||
"unicode"
|
"unicode"
|
||||||
],
|
],
|
||||||
"time": "2017-03-23 17:02:28"
|
"time": "2017-03-23T17:02:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "grasmash/expander",
|
"name": "grasmash/expander",
|
||||||
@@ -714,7 +773,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Expands internal property references in PHP arrays file.",
|
"description": "Expands internal property references in PHP arrays file.",
|
||||||
"time": "2017-12-21 22:14:55"
|
"time": "2017-12-21T22:14:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "grasmash/yaml-expander",
|
"name": "grasmash/yaml-expander",
|
||||||
@@ -762,7 +821,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Expands internal property references in a yaml file.",
|
"description": "Expands internal property references in a yaml file.",
|
||||||
"time": "2017-12-16 16:06:03"
|
"time": "2017-12-16T16:06:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/container",
|
"name": "league/container",
|
||||||
@@ -827,7 +886,7 @@
|
|||||||
"provider",
|
"provider",
|
||||||
"service"
|
"service"
|
||||||
],
|
],
|
||||||
"time": "2017-05-10 09:20:27"
|
"time": "2017-05-10T09:20:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
@@ -900,7 +959,41 @@
|
|||||||
"logging",
|
"logging",
|
||||||
"psr-3"
|
"psr-3"
|
||||||
],
|
],
|
||||||
"time": "2015-03-09 09:58:04"
|
"time": "2015-03-09T09:58:04+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "neitanod/forceutf8",
|
||||||
|
"version": "v2.0.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/neitanod/forceutf8.git",
|
||||||
|
"reference": "47c883ab2739e7938a8bb0bfd1c29d48c88858de"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/neitanod/forceutf8/zipball/47c883ab2739e7938a8bb0bfd1c29d48c88858de",
|
||||||
|
"reference": "47c883ab2739e7938a8bb0bfd1c29d48c88858de",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"ForceUTF8\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sebastián Grignoli",
|
||||||
|
"email": "grignoli@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.",
|
||||||
|
"homepage": "https://github.com/neitanod/forceutf8",
|
||||||
|
"time": "2017-05-22T18:50:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pear/console_getopt",
|
"name": "pear/console_getopt",
|
||||||
@@ -947,7 +1040,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "More info available on: http://pear.php.net/package/Console_Getopt",
|
"description": "More info available on: http://pear.php.net/package/Console_Getopt",
|
||||||
"time": "2015-07-20 20:28:12"
|
"time": "2015-07-20T20:28:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pear/mail",
|
"name": "pear/mail",
|
||||||
@@ -1005,7 +1098,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Class that provides multiple interfaces for sending emails.",
|
"description": "Class that provides multiple interfaces for sending emails.",
|
||||||
"homepage": "http://pear.php.net/package/Mail",
|
"homepage": "http://pear.php.net/package/Mail",
|
||||||
"time": "2017-04-11 17:27:29"
|
"time": "2017-04-11T17:27:29+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pear/net_smtp",
|
"name": "pear/net_smtp",
|
||||||
@@ -1065,7 +1158,7 @@
|
|||||||
"mail",
|
"mail",
|
||||||
"smtp"
|
"smtp"
|
||||||
],
|
],
|
||||||
"time": "2017-01-14 18:19:55"
|
"time": "2017-01-14T18:19:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pear/net_socket",
|
"name": "pear/net_socket",
|
||||||
@@ -1119,7 +1212,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "More info available on: http://pear.php.net/package/Net_Socket",
|
"description": "More info available on: http://pear.php.net/package/Net_Socket",
|
||||||
"time": "2017-04-06 15:16:38"
|
"time": "2017-04-06T15:16:38+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pear/pear-core-minimal",
|
"name": "pear/pear-core-minimal",
|
||||||
@@ -1163,7 +1256,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Minimal set of PEAR core files to be used as composer dependency",
|
"description": "Minimal set of PEAR core files to be used as composer dependency",
|
||||||
"time": "2017-02-28 16:46:11"
|
"time": "2017-02-28T16:46:11+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pear/pear_exception",
|
"name": "pear/pear_exception",
|
||||||
@@ -1218,7 +1311,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"exception"
|
"exception"
|
||||||
],
|
],
|
||||||
"time": "2015-02-10 20:07:52"
|
"time": "2015-02-10T20:07:52+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/container",
|
"name": "psr/container",
|
||||||
@@ -1267,7 +1360,7 @@
|
|||||||
"container-interop",
|
"container-interop",
|
||||||
"psr"
|
"psr"
|
||||||
],
|
],
|
||||||
"time": "2017-02-14 16:28:37"
|
"time": "2017-02-14T16:28:37+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
@@ -1314,7 +1407,59 @@
|
|||||||
"psr",
|
"psr",
|
||||||
"psr-3"
|
"psr-3"
|
||||||
],
|
],
|
||||||
"time": "2016-10-10 12:19:37"
|
"time": "2016-10-10T12:19:37+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spomky-labs/base64url",
|
||||||
|
"version": "v1.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Spomky-Labs/base64url.git",
|
||||||
|
"reference": "ef6d5fb93894063d9cee996022259fd08d6646ea"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Spomky-Labs/base64url/zipball/ef6d5fb93894063d9cee996022259fd08d6646ea",
|
||||||
|
"reference": "ef6d5fb93894063d9cee996022259fd08d6646ea",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^5.3|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.0|^5.0",
|
||||||
|
"satooshi/php-coveralls": "^1.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Base64Url\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Florent Morselli",
|
||||||
|
"homepage": "https://github.com/Spomky-Labs/base64url/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Base 64 URL Safe Encoding/decoding PHP Library",
|
||||||
|
"homepage": "https://github.com/Spomky-Labs/base64url",
|
||||||
|
"keywords": [
|
||||||
|
"base64",
|
||||||
|
"rfc4648",
|
||||||
|
"safe",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"time": "2016-01-21T19:50:30+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "swiftmailer/swiftmailer",
|
"name": "swiftmailer/swiftmailer",
|
||||||
@@ -1369,7 +1514,7 @@
|
|||||||
"mail",
|
"mail",
|
||||||
"mailer"
|
"mailer"
|
||||||
],
|
],
|
||||||
"time": "2017-09-30 22:39:41"
|
"time": "2017-09-30T22:39:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
@@ -1438,7 +1583,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 07:37:34"
|
"time": "2018-01-03T07:37:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/debug",
|
"name": "symfony/debug",
|
||||||
@@ -1494,7 +1639,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Debug Component",
|
"description": "Symfony Debug Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 17:14:19"
|
"time": "2018-01-03T17:14:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
@@ -1557,7 +1702,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Symfony EventDispatcher Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 07:37:34"
|
"time": "2018-01-03T07:37:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
@@ -1606,7 +1751,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Filesystem Component",
|
"description": "Symfony Filesystem Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 07:37:34"
|
"time": "2018-01-03T07:37:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
@@ -1655,7 +1800,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Symfony Finder Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 07:37:34"
|
"time": "2018-01-03T07:37:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
@@ -1714,7 +1859,7 @@
|
|||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"time": "2017-10-11 12:05:26"
|
"time": "2017-10-11T12:05:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/process",
|
"name": "symfony/process",
|
||||||
@@ -1763,7 +1908,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Process Component",
|
"description": "Symfony Process Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 07:37:34"
|
"time": "2018-01-03T07:37:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
@@ -1821,7 +1966,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Yaml Component",
|
"description": "Symfony Yaml Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2018-01-03 07:37:34"
|
"time": "2018-01-03T07:37:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
@@ -1882,7 +2027,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"templating"
|
"templating"
|
||||||
],
|
],
|
||||||
"time": "2016-01-11 14:02:19"
|
"time": "2016-01-11T14:02:19+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
@@ -1938,7 +2083,7 @@
|
|||||||
"constructor",
|
"constructor",
|
||||||
"instantiate"
|
"instantiate"
|
||||||
],
|
],
|
||||||
"time": "2015-06-14 21:17:01"
|
"time": "2015-06-14T21:17:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "myclabs/deep-copy",
|
"name": "myclabs/deep-copy",
|
||||||
@@ -1983,7 +2128,7 @@
|
|||||||
"object",
|
"object",
|
||||||
"object graph"
|
"object graph"
|
||||||
],
|
],
|
||||||
"time": "2017-10-19 19:58:43"
|
"time": "2017-10-19T19:58:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phar-io/manifest",
|
"name": "phar-io/manifest",
|
||||||
@@ -2038,7 +2183,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
||||||
"time": "2017-03-05 18:14:27"
|
"time": "2017-03-05T18:14:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phar-io/version",
|
"name": "phar-io/version",
|
||||||
@@ -2085,7 +2230,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Library for handling version information and constraints",
|
"description": "Library for handling version information and constraints",
|
||||||
"time": "2017-03-05 17:38:23"
|
"time": "2017-03-05T17:38:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-common",
|
"name": "phpdocumentor/reflection-common",
|
||||||
@@ -2139,7 +2284,7 @@
|
|||||||
"reflection",
|
"reflection",
|
||||||
"static analysis"
|
"static analysis"
|
||||||
],
|
],
|
||||||
"time": "2017-09-11 18:02:19"
|
"time": "2017-09-11T18:02:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-docblock",
|
"name": "phpdocumentor/reflection-docblock",
|
||||||
@@ -2190,7 +2335,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||||
"time": "2017-11-27 17:38:31"
|
"time": "2017-11-27T17:38:31+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/type-resolver",
|
"name": "phpdocumentor/type-resolver",
|
||||||
@@ -2237,7 +2382,7 @@
|
|||||||
"email": "me@mikevanriel.com"
|
"email": "me@mikevanriel.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2017-07-14 14:27:02"
|
"time": "2017-07-14T14:27:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpspec/prophecy",
|
"name": "phpspec/prophecy",
|
||||||
@@ -2300,7 +2445,7 @@
|
|||||||
"spy",
|
"spy",
|
||||||
"stub"
|
"stub"
|
||||||
],
|
],
|
||||||
"time": "2017-11-24 13:59:53"
|
"time": "2017-11-24T13:59:53+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
@@ -2363,7 +2508,7 @@
|
|||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"time": "2017-12-06 09:29:45"
|
"time": "2017-12-06T09:29:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-file-iterator",
|
"name": "phpunit/php-file-iterator",
|
||||||
@@ -2410,7 +2555,7 @@
|
|||||||
"filesystem",
|
"filesystem",
|
||||||
"iterator"
|
"iterator"
|
||||||
],
|
],
|
||||||
"time": "2017-11-27 13:52:08"
|
"time": "2017-11-27T13:52:08+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-text-template",
|
"name": "phpunit/php-text-template",
|
||||||
@@ -2451,7 +2596,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"template"
|
"template"
|
||||||
],
|
],
|
||||||
"time": "2015-06-21 13:50:34"
|
"time": "2015-06-21T13:50:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-timer",
|
"name": "phpunit/php-timer",
|
||||||
@@ -2500,7 +2645,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"timer"
|
"timer"
|
||||||
],
|
],
|
||||||
"time": "2017-02-26 11:10:40"
|
"time": "2017-02-26T11:10:40+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-token-stream",
|
"name": "phpunit/php-token-stream",
|
||||||
@@ -2549,7 +2694,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"tokenizer"
|
"tokenizer"
|
||||||
],
|
],
|
||||||
"time": "2017-11-27 05:48:46"
|
"time": "2017-11-27T05:48:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
@@ -2633,7 +2778,7 @@
|
|||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"time": "2017-12-17 06:31:19"
|
"time": "2017-12-17T06:31:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit-mock-objects",
|
"name": "phpunit/phpunit-mock-objects",
|
||||||
@@ -2692,7 +2837,7 @@
|
|||||||
"mock",
|
"mock",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"time": "2018-01-06 05:45:45"
|
"time": "2018-01-06T05:45:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/code-unit-reverse-lookup",
|
"name": "sebastian/code-unit-reverse-lookup",
|
||||||
@@ -2737,7 +2882,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Looks up which function or method a line of code belongs to",
|
"description": "Looks up which function or method a line of code belongs to",
|
||||||
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
|
||||||
"time": "2017-03-04 06:30:41"
|
"time": "2017-03-04T06:30:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/comparator",
|
"name": "sebastian/comparator",
|
||||||
@@ -2801,7 +2946,7 @@
|
|||||||
"compare",
|
"compare",
|
||||||
"equality"
|
"equality"
|
||||||
],
|
],
|
||||||
"time": "2017-12-22 14:50:35"
|
"time": "2017-12-22T14:50:35+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/diff",
|
"name": "sebastian/diff",
|
||||||
@@ -2853,7 +2998,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"diff"
|
"diff"
|
||||||
],
|
],
|
||||||
"time": "2017-08-03 08:09:46"
|
"time": "2017-08-03T08:09:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/environment",
|
"name": "sebastian/environment",
|
||||||
@@ -2903,7 +3048,7 @@
|
|||||||
"environment",
|
"environment",
|
||||||
"hhvm"
|
"hhvm"
|
||||||
],
|
],
|
||||||
"time": "2017-07-01 08:51:00"
|
"time": "2017-07-01T08:51:00+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/exporter",
|
"name": "sebastian/exporter",
|
||||||
@@ -2970,7 +3115,7 @@
|
|||||||
"export",
|
"export",
|
||||||
"exporter"
|
"exporter"
|
||||||
],
|
],
|
||||||
"time": "2017-04-03 13:19:02"
|
"time": "2017-04-03T13:19:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/global-state",
|
"name": "sebastian/global-state",
|
||||||
@@ -3021,7 +3166,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"global state"
|
"global state"
|
||||||
],
|
],
|
||||||
"time": "2017-04-27 15:39:26"
|
"time": "2017-04-27T15:39:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/object-enumerator",
|
"name": "sebastian/object-enumerator",
|
||||||
@@ -3068,7 +3213,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
|
||||||
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
|
||||||
"time": "2017-08-03 12:35:26"
|
"time": "2017-08-03T12:35:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/object-reflector",
|
"name": "sebastian/object-reflector",
|
||||||
@@ -3113,7 +3258,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
"description": "Allows reflection of object attributes, including inherited and non-public ones",
|
||||||
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
|
||||||
"time": "2017-03-29 09:07:27"
|
"time": "2017-03-29T09:07:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/recursion-context",
|
"name": "sebastian/recursion-context",
|
||||||
@@ -3166,7 +3311,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Provides functionality to recursively process PHP variables",
|
"description": "Provides functionality to recursively process PHP variables",
|
||||||
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
||||||
"time": "2017-03-03 06:23:57"
|
"time": "2017-03-03T06:23:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/resource-operations",
|
"name": "sebastian/resource-operations",
|
||||||
@@ -3208,7 +3353,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Provides a list of PHP built-in functions that operate on resources",
|
"description": "Provides a list of PHP built-in functions that operate on resources",
|
||||||
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
|
||||||
"time": "2015-07-28 20:34:47"
|
"time": "2015-07-28T20:34:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/version",
|
"name": "sebastian/version",
|
||||||
@@ -3251,7 +3396,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||||
"homepage": "https://github.com/sebastianbergmann/version",
|
"homepage": "https://github.com/sebastianbergmann/version",
|
||||||
"time": "2016-10-03 07:35:21"
|
"time": "2016-10-03T07:35:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
@@ -3291,7 +3436,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
|
||||||
"time": "2017-04-07 12:08:54"
|
"time": "2017-04-07T12:08:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
@@ -3341,7 +3486,7 @@
|
|||||||
"check",
|
"check",
|
||||||
"validate"
|
"validate"
|
||||||
],
|
],
|
||||||
"time": "2016-11-23 20:04:58"
|
"time": "2016-11-23T20:04:58+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
|||||||
2
core/lib/composer/vendor/autoload.php
vendored
2
core/lib/composer/vendor/autoload.php
vendored
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
// autoload.php @generated by Composer
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
return ComposerAutoloaderInit6d4a28cd96a5bc5d5b97781c062572d9::getLoader();
|
return ComposerAutoloaderInit6d4a28cd96a5bc5d5b97781c062572d9::getLoader();
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../gettext/languages/bin/export-plural-rules
|
|
||||||
4
core/lib/composer/vendor/bin/export-plural-rules
vendored
Executable file
4
core/lib/composer/vendor/bin/export-plural-rules
vendored
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include 'export-plural-rules.php';
|
||||||
@@ -1 +0,0 @@
|
|||||||
../gettext/languages/bin/export-plural-rules.php
|
|
||||||
234
core/lib/composer/vendor/bin/export-plural-rules.php
vendored
Executable file
234
core/lib/composer/vendor/bin/export-plural-rules.php
vendored
Executable file
@@ -0,0 +1,234 @@
|
|||||||
|
<?php
|
||||||
|
use Gettext\Languages\Exporter\Exporter;
|
||||||
|
use Gettext\Languages\Language;
|
||||||
|
|
||||||
|
// Let's start by imposing that we don't accept any error or warning.
|
||||||
|
// This is a really life-saving approach.
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
|
||||||
|
Enviro::echoErr("$errstr\nFile: $errfile\nLine: $errline\nCode: $errno\n");
|
||||||
|
die(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
require_once dirname(__DIR__).'/src/autoloader.php';
|
||||||
|
|
||||||
|
// Parse the command line options
|
||||||
|
Enviro::initialize();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isset(Enviro::$languages)) {
|
||||||
|
$languages = array();
|
||||||
|
foreach (Enviro::$languages as $languageId) {
|
||||||
|
$language = Language::getById($languageId);
|
||||||
|
if (!isset($language)) {
|
||||||
|
throw new Exception("Unable to find the language with id '$languageId'");
|
||||||
|
}
|
||||||
|
$languages[] = $language;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$languages = Language::getAll();
|
||||||
|
}
|
||||||
|
if (Enviro::$reduce) {
|
||||||
|
$languages = Enviro::reduce($languages);
|
||||||
|
}
|
||||||
|
if (isset(Enviro::$outputFilename)) {
|
||||||
|
echo call_user_func(array(Exporter::getExporterClassName(Enviro::$outputFormat), 'toFile'), $languages, Enviro::$outputFilename, array('us-ascii' => Enviro::$outputUSAscii));
|
||||||
|
} else {
|
||||||
|
echo call_user_func(array(Exporter::getExporterClassName(Enviro::$outputFormat), 'toString'), $languages, array('us-ascii' => Enviro::$outputUSAscii));
|
||||||
|
}
|
||||||
|
} catch (Exception $x) {
|
||||||
|
Enviro::echoErr($x->getMessage()."\n");
|
||||||
|
Enviro::echoErr("Trace:\n");
|
||||||
|
Enviro::echoErr($x->getTraceAsString()."\n");
|
||||||
|
die(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
die(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to handle command line options.
|
||||||
|
*/
|
||||||
|
class Enviro
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Shall the output contain only US-ASCII characters?
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public static $outputUSAscii;
|
||||||
|
/**
|
||||||
|
* The output format.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $outputFormat;
|
||||||
|
/**
|
||||||
|
* Output file name.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $outputFilename;
|
||||||
|
/**
|
||||||
|
* List of wanted language IDs; it not set: all languages will be returned.
|
||||||
|
* @var array|null
|
||||||
|
*/
|
||||||
|
public static $languages;
|
||||||
|
/**
|
||||||
|
* Reduce the language list to the minimum common denominator.
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
public static $reduce;
|
||||||
|
/**
|
||||||
|
* Parse the command line options.
|
||||||
|
*/
|
||||||
|
public static function initialize()
|
||||||
|
{
|
||||||
|
global $argv;
|
||||||
|
self::$outputUSAscii = false;
|
||||||
|
self::$outputFormat = null;
|
||||||
|
self::$outputFilename = null;
|
||||||
|
self::$languages = null;
|
||||||
|
self::$reduce = null;
|
||||||
|
$exporters = Exporter::getExporters();
|
||||||
|
if (isset($argv) && is_array($argv)) {
|
||||||
|
foreach ($argv as $argi => $arg) {
|
||||||
|
if ($argi === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_string($arg)) {
|
||||||
|
$argLC = trim(strtolower($arg));
|
||||||
|
switch ($argLC) {
|
||||||
|
case '--us-ascii':
|
||||||
|
self::$outputUSAscii = true;
|
||||||
|
break;
|
||||||
|
case '--reduce=yes':
|
||||||
|
self::$reduce = true;
|
||||||
|
break;
|
||||||
|
case '--reduce=no':
|
||||||
|
self::$reduce = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (preg_match('/^--output=.+$/', $argLC)) {
|
||||||
|
if (isset(self::$outputFilename)) {
|
||||||
|
self::echoErr("The output file name has been specified more than once!\n");
|
||||||
|
self::showSyntax();
|
||||||
|
die(3);
|
||||||
|
}
|
||||||
|
list(, self::$outputFilename) = explode('=', $arg, 2);
|
||||||
|
self::$outputFilename = trim(self::$outputFilename);
|
||||||
|
} elseif (preg_match('/^--languages?=.+$/', $argLC)) {
|
||||||
|
list(, $s) = explode('=', $arg, 2);
|
||||||
|
$list = explode(',', $s);
|
||||||
|
if (is_array(self::$languages)) {
|
||||||
|
self::$languages = array_merge(self::$languages, $list);
|
||||||
|
} else {
|
||||||
|
self::$languages = $list;
|
||||||
|
}
|
||||||
|
} elseif (isset($exporters[$argLC])) {
|
||||||
|
if (isset(self::$outputFormat)) {
|
||||||
|
self::echoErr("The output format has been specified more than once!\n");
|
||||||
|
self::showSyntax();
|
||||||
|
die(3);
|
||||||
|
}
|
||||||
|
self::$outputFormat = $argLC;
|
||||||
|
} else {
|
||||||
|
self::echoErr("Unknown option: $arg\n");
|
||||||
|
self::showSyntax();
|
||||||
|
die(2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset(self::$outputFormat)) {
|
||||||
|
self::showSyntax();
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
if (isset(self::$languages)) {
|
||||||
|
self::$languages = array_values(array_unique(self::$languages));
|
||||||
|
}
|
||||||
|
if (!isset(self::$reduce)) {
|
||||||
|
self::$reduce = isset(self::$languages) ? false : true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write out the syntax.
|
||||||
|
*/
|
||||||
|
public static function showSyntax()
|
||||||
|
{
|
||||||
|
$exporters = array_keys(Exporter::getExporters(true));
|
||||||
|
self::echoErr("Syntax: php ".basename(__FILE__)." [--us-ascii] [--languages=<LanguageId>[,<LanguageId>,...]] [--reduce=yes|no] [--output=<file name>] <".implode('|', $exporters).">\n");
|
||||||
|
self::echoErr("Where:\n");
|
||||||
|
self::echoErr("--us-ascii : if specified, the output will contain only US-ASCII characters.\n");
|
||||||
|
self::echoErr("--languages: (or --language) export only the specified language codes.\n");
|
||||||
|
self::echoErr(" Separate languages with commas; you can also use this argument\n");
|
||||||
|
self::echoErr(" more than once; it's case insensitive and accepts both '_' and\n");
|
||||||
|
self::echoErr(" '-' as locale chunks separator (eg we accept 'it_IT' as well as\n");
|
||||||
|
self::echoErr(" 'it-it').\n");
|
||||||
|
self::echoErr("--reduce : if set to yes the output won't contain languages with the same\n");
|
||||||
|
self::echoErr(" base language and rules.\n For instance nl_BE ('Flemish') will be\n");
|
||||||
|
self::echoErr(" omitted because it's the same as nl ('Dutch').\n");
|
||||||
|
self::echoErr(" Defaults to 'no' --languages is specified, to 'yes' otherwise.\n");
|
||||||
|
self::echoErr("--output : if specified, the output will be saved to <file name>. If not\n");
|
||||||
|
self::echoErr(" specified we'll output to standard output.\n");
|
||||||
|
self::echoErr("Output formats\n");
|
||||||
|
$len = max(array_map('strlen', $exporters));
|
||||||
|
foreach ($exporters as $exporter) {
|
||||||
|
self::echoErr(str_pad($exporter, $len).": ".Exporter::getExporterDescription($exporter)."\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Print a string to stderr.
|
||||||
|
* @param string $str The string to be printed out.
|
||||||
|
*/
|
||||||
|
public static function echoErr($str)
|
||||||
|
{
|
||||||
|
$hStdErr = @fopen('php://stderr', 'a');
|
||||||
|
if ($hStdErr === false) {
|
||||||
|
echo $str;
|
||||||
|
} else {
|
||||||
|
fwrite($hStdErr, $str);
|
||||||
|
fclose($hStdErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reduce a language list to the minimum common denominator.
|
||||||
|
* @param Language[] $languages
|
||||||
|
* @return Language[]
|
||||||
|
*/
|
||||||
|
public static function reduce($languages)
|
||||||
|
{
|
||||||
|
for ($numChunks = 3; $numChunks >= 2; $numChunks--) {
|
||||||
|
$filtered = array();
|
||||||
|
foreach ($languages as $language) {
|
||||||
|
$chunks = explode('_', $language->id);
|
||||||
|
$compatibleFound = false;
|
||||||
|
if (count($chunks) === $numChunks) {
|
||||||
|
$categoriesHash = serialize($language->categories);
|
||||||
|
$otherIds = array();
|
||||||
|
$otherIds[] = $chunks[0];
|
||||||
|
for ($k = 2; $k < $numChunks; $k++) {
|
||||||
|
$otherIds[] = $chunks[0].'_'.$chunks[$numChunks - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($languages as $check) {
|
||||||
|
foreach ($otherIds as $otherId) {
|
||||||
|
if (($check->id === $otherId) && ($check->formula === $language->formula) && (serialize($check->categories) === $categoriesHash)) {
|
||||||
|
$compatibleFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($compatibleFound === true) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$compatibleFound) {
|
||||||
|
$filtered[] = $language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$languages = $filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $languages;
|
||||||
|
}
|
||||||
|
}
|
||||||
170
core/lib/composer/vendor/bin/markdown
vendored
Executable file
170
core/lib/composer/vendor/bin/markdown
vendored
Executable file
@@ -0,0 +1,170 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
$composerAutoload = [
|
||||||
|
__DIR__ . '/../vendor/autoload.php', // standalone with "composer install" run
|
||||||
|
__DIR__ . '/../../../autoload.php', // script is installed as a composer binary
|
||||||
|
];
|
||||||
|
foreach ($composerAutoload as $autoload) {
|
||||||
|
if (file_exists($autoload)) {
|
||||||
|
require($autoload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all errors to stderr
|
||||||
|
ini_set('display_errors', 'stderr');
|
||||||
|
|
||||||
|
$flavor = 'cebe\\markdown\\Markdown';
|
||||||
|
$flavors = [
|
||||||
|
'gfm' => ['cebe\\markdown\\GithubMarkdown', __DIR__ . '/../GithubMarkdown.php'],
|
||||||
|
'extra' => ['cebe\\markdown\\MarkdownExtra', __DIR__ . '/../MarkdownExtra.php'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$full = false;
|
||||||
|
$src = [];
|
||||||
|
foreach($argv as $k => $arg) {
|
||||||
|
if ($k == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($arg[0] == '-') {
|
||||||
|
$arg = explode('=', $arg);
|
||||||
|
switch($arg[0]) {
|
||||||
|
case '--flavor':
|
||||||
|
if (isset($arg[1])) {
|
||||||
|
if (isset($flavors[$arg[1]])) {
|
||||||
|
require($flavors[$arg[1]][1]);
|
||||||
|
$flavor = $flavors[$arg[1]][0];
|
||||||
|
} else {
|
||||||
|
error("Unknown flavor: " . $arg[1], "usage");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error("Incomplete argument --flavor!", "usage");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '--full':
|
||||||
|
$full = true;
|
||||||
|
break;
|
||||||
|
case '-h':
|
||||||
|
case '--help':
|
||||||
|
echo "PHP Markdown to HTML converter\n";
|
||||||
|
echo "------------------------------\n\n";
|
||||||
|
echo "by Carsten Brandt <mail@cebe.cc>\n\n";
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unknown argument " . $arg[0], "usage");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$src[] = $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($src)) {
|
||||||
|
$markdown = file_get_contents("php://stdin");
|
||||||
|
} elseif (count($src) == 1) {
|
||||||
|
$file = reset($src);
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
error("File does not exist:" . $file);
|
||||||
|
}
|
||||||
|
$markdown = file_get_contents($file);
|
||||||
|
} else {
|
||||||
|
error("Converting multiple files is not yet supported.", "usage");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var cebe\markdown\Parser $md */
|
||||||
|
$md = new $flavor();
|
||||||
|
$markup = $md->parse($markdown);
|
||||||
|
|
||||||
|
if ($full) {
|
||||||
|
echo <<<HTML
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; }
|
||||||
|
code { background: #eeeeff; padding: 2px; }
|
||||||
|
li { margin-bottom: 5px; }
|
||||||
|
img { max-width: 1200px; }
|
||||||
|
table, td, th { border: solid 1px #ccc; border-collapse: collapse; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
$markup
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML;
|
||||||
|
} else {
|
||||||
|
echo $markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display usage information
|
||||||
|
*/
|
||||||
|
function usage() {
|
||||||
|
global $argv;
|
||||||
|
$cmd = $argv[0];
|
||||||
|
echo <<<EOF
|
||||||
|
Usage:
|
||||||
|
$cmd [--flavor=<flavor>] [--full] [file.md]
|
||||||
|
|
||||||
|
--flavor specifies the markdown flavor to use. If omitted the original markdown by John Gruber [1] will be used.
|
||||||
|
Available flavors:
|
||||||
|
|
||||||
|
gfm - Github flavored markdown [2]
|
||||||
|
extra - Markdown Extra [3]
|
||||||
|
|
||||||
|
--full ouput a full HTML page with head and body. If not given, only the parsed markdown will be output.
|
||||||
|
|
||||||
|
--help shows this usage information.
|
||||||
|
|
||||||
|
If no file is specified input will be read from STDIN.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Render a file with original markdown:
|
||||||
|
|
||||||
|
$cmd README.md > README.html
|
||||||
|
|
||||||
|
Render a file using gihtub flavored markdown:
|
||||||
|
|
||||||
|
$cmd --flavor=gfm README.md > README.html
|
||||||
|
|
||||||
|
Convert the original markdown description to html using STDIN:
|
||||||
|
|
||||||
|
curl http://daringfireball.net/projects/markdown/syntax.text | $cmd > md.html
|
||||||
|
|
||||||
|
|
||||||
|
[1] http://daringfireball.net/projects/markdown/syntax
|
||||||
|
[2] https://help.github.com/articles/github-flavored-markdown
|
||||||
|
[3] http://michelf.ca/projects/php-markdown/extra/
|
||||||
|
|
||||||
|
EOF;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send custom error message to stderr
|
||||||
|
* @param $message string
|
||||||
|
* @param $callback mixed called before script exit
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function error($message, $callback = null) {
|
||||||
|
$fe = fopen("php://stderr", "w");
|
||||||
|
fwrite($fe, "Error: " . $message . "\n");
|
||||||
|
|
||||||
|
if (is_callable($callback)) {
|
||||||
|
call_user_func($callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
1
core/lib/composer/vendor/bin/phpunit
vendored
1
core/lib/composer/vendor/bin/phpunit
vendored
@@ -1 +0,0 @@
|
|||||||
../phpunit/phpunit/phpunit
|
|
||||||
53
core/lib/composer/vendor/bin/phpunit
vendored
Executable file
53
core/lib/composer/vendor/bin/phpunit
vendored
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of PHPUnit.
|
||||||
|
*
|
||||||
|
* (c) Sebastian Bergmann <sebastian@phpunit.de>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (version_compare('7.0.0', PHP_VERSION, '>')) {
|
||||||
|
fwrite(
|
||||||
|
STDERR,
|
||||||
|
sprintf(
|
||||||
|
'This version of PHPUnit is supported on PHP 7.0 and PHP 7.1.' . PHP_EOL .
|
||||||
|
'You are using PHP %s (%s).' . PHP_EOL,
|
||||||
|
PHP_VERSION,
|
||||||
|
PHP_BINARY
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ini_get('date.timezone')) {
|
||||||
|
ini_set('date.timezone', 'UTC');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) {
|
||||||
|
if (file_exists($file)) {
|
||||||
|
define('PHPUNIT_COMPOSER_INSTALL', $file);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($file);
|
||||||
|
|
||||||
|
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
|
||||||
|
fwrite(
|
||||||
|
STDERR,
|
||||||
|
'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL .
|
||||||
|
' composer install' . PHP_EOL . PHP_EOL .
|
||||||
|
'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL
|
||||||
|
);
|
||||||
|
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require PHPUNIT_COMPOSER_INSTALL;
|
||||||
|
|
||||||
|
PHPUnit\TextUI\Command::main();
|
||||||
1
core/lib/composer/vendor/bin/robo
vendored
1
core/lib/composer/vendor/bin/robo
vendored
@@ -1 +0,0 @@
|
|||||||
../consolidation/robo/robo
|
|
||||||
22
core/lib/composer/vendor/bin/robo
vendored
Executable file
22
core/lib/composer/vendor/bin/robo
vendored
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if we're running from phar load the phar autoload,
|
||||||
|
* else let the script 'robo' search for the autoloader
|
||||||
|
*/
|
||||||
|
if (strpos(basename(__FILE__), 'phar')) {
|
||||||
|
require_once 'phar://robo.phar/vendor/autoload.php';
|
||||||
|
} else {
|
||||||
|
if (file_exists(__DIR__.'/vendor/autoload.php')) {
|
||||||
|
require_once __DIR__.'/vendor/autoload.php';
|
||||||
|
} elseif (file_exists(__DIR__.'/../../autoload.php')) {
|
||||||
|
require_once __DIR__ . '/../../autoload.php';
|
||||||
|
} else {
|
||||||
|
require_once 'phar://robo.phar/vendor/autoload.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$runner = new \Robo\Runner();
|
||||||
|
$runner->setSelfUpdateRepository('consolidation/robo');
|
||||||
|
$statusCode = $runner->execute($_SERVER['argv']);
|
||||||
|
exit($statusCode);
|
||||||
6
core/lib/composer/vendor/cebe/markdown/.gitattributes
vendored
Normal file
6
core/lib/composer/vendor/cebe/markdown/.gitattributes
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
* text=auto
|
||||||
|
|
||||||
|
/.gitattributes
|
||||||
|
/.gitignore
|
||||||
|
/.scrutinizer.yml
|
||||||
|
/.travis.yml
|
||||||
4
core/lib/composer/vendor/cebe/markdown/.gitignore
vendored
Normal file
4
core/lib/composer/vendor/cebe/markdown/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/.idea/
|
||||||
|
composer.lock
|
||||||
|
/vendor
|
||||||
|
README.html
|
||||||
6
core/lib/composer/vendor/cebe/markdown/.scrutinizer.yml
vendored
Normal file
6
core/lib/composer/vendor/cebe/markdown/.scrutinizer.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
imports:
|
||||||
|
- php
|
||||||
|
|
||||||
|
tools:
|
||||||
|
external_code_coverage:
|
||||||
|
timeout: 600 # Timeout in seconds.
|
||||||
42
core/lib/composer/vendor/cebe/markdown/.travis.yml
vendored
Normal file
42
core/lib/composer/vendor/cebe/markdown/.travis.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
language: php
|
||||||
|
|
||||||
|
php:
|
||||||
|
- 5.4
|
||||||
|
- 5.5
|
||||||
|
- 5.6
|
||||||
|
- 7.0
|
||||||
|
- 7.1
|
||||||
|
- 7.2
|
||||||
|
- nightly
|
||||||
|
- hhvm
|
||||||
|
|
||||||
|
# faster builds on new travis setup not using sudo
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
# travis does not support HHVM on other platforms, choosing trusty
|
||||||
|
dist: trusty
|
||||||
|
|
||||||
|
# cache composer cache
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.composer/cache
|
||||||
|
|
||||||
|
# run build against hhvm but allow them to fail
|
||||||
|
# http://docs.travis-ci.com/user/build-configuration/#Rows-That-are-Allowed-To-Fail
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
allow_failures:
|
||||||
|
- php: nightly
|
||||||
|
|
||||||
|
install:
|
||||||
|
- composer self-update && composer --version
|
||||||
|
- composer install --prefer-dist
|
||||||
|
|
||||||
|
script:
|
||||||
|
- vendor/bin/phpunit --verbose --coverage-clover=coverage.clover
|
||||||
|
# test against standard markdown spec
|
||||||
|
# - git clone https://github.com/jgm/stmd && cd stmd && perl runtests.pl spec.txt ../bin/markdown
|
||||||
|
|
||||||
|
after_script:
|
||||||
|
- wget https://scrutinizer-ci.com/ocular.phar
|
||||||
|
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
||||||
104
core/lib/composer/vendor/cebe/markdown/CHANGELOG.md
vendored
Normal file
104
core/lib/composer/vendor/cebe/markdown/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
CHANGELOG
|
||||||
|
=========
|
||||||
|
|
||||||
|
Version 1.2.1 on 26. Mar. 2018
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
- Improved handling of inline HTML with URL and email tags.
|
||||||
|
- Improved handling of custom syntax with `[[`, references should not use `[` as the first character in the reference name.
|
||||||
|
|
||||||
|
Version 1.2.0 on 14. Mar. 2018
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
- #50 Do not render empty emphs.
|
||||||
|
- #69 Improve ABSY for tables, make column and row information directly available in absy (@NathanBaulch)
|
||||||
|
- #89 Lists should be separated by a HR (@bieleckim)
|
||||||
|
- #95 Added `TableTrait::composeTable($head, $body)`, for easier overriding of table layout (@maximal, @cebe)
|
||||||
|
- #111 Improve rendering of successive strongs (@wogsland)
|
||||||
|
- #132 Improve detection and rendering of fenced code blocks in lists.
|
||||||
|
- #134 Fix Emph and Strong to allow escaping `*` or `_` inside them.
|
||||||
|
- #135 GithubMarkdown was not parsing inline code when there are square brackets around it.
|
||||||
|
- #151 Fixed table rendering for lines begining with | for GFM (@GenaBitu)
|
||||||
|
- Improved table rendering, allow single column tables.
|
||||||
|
|
||||||
|
Version 1.1.2 on 16. Jul 2017
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
- #126 Fixed crash on empty lines that extend a lazy list
|
||||||
|
- #128 Fix table renderer which including default alignment (@tanakahisateru)
|
||||||
|
- #129 Use given encoded URL if decoded URL text looks insecure, e.g. uses broken UTF-8 (@tanakahisateru)
|
||||||
|
- Added a workaround for a [PHP bug](https://bugs.php.net/bug.php?id=45735) which exists in versions `<` 7.0, where `preg_match()` causes a segfault
|
||||||
|
on [catastropic backtracking][] in emph/strong parsing.
|
||||||
|
|
||||||
|
[catastropic backtracking]: http://www.regular-expressions.info/catastrophic.html
|
||||||
|
|
||||||
|
Version 1.1.1 on 14. Sep 2016
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
- #112 Fixed parsing for custom self-closing HTML tags
|
||||||
|
- #113 improve extensibility by making `prepareMarkers()` protected and add `parseBlock()` method
|
||||||
|
- #114 better handling of continued inline HTML in paragraphs
|
||||||
|
|
||||||
|
Version 1.1.0 on 06. Mar. 2015
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
- improve compatibility with github flavored markdown
|
||||||
|
- #64 fixed some rendering issue with emph and strong
|
||||||
|
- #56 trailing and leading spaces in a link are now ignored
|
||||||
|
- fixed various issues with table rendering
|
||||||
|
- #98 Fix PHP fatal error when maximumNestingLevel was reached (@tanakahisateru)
|
||||||
|
- refactored nested and lazy list handling, improved overall list rendering consistency
|
||||||
|
- Lines containing "0" where skipped or considered empty in some cases (@tanakahisateru)
|
||||||
|
- #54 escape characters are now also considered inside of urls
|
||||||
|
|
||||||
|
Version 1.0.1 on 25. Oct. 2014
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
- Fixed the `bin/markdown` script to work with composer autoloader (c497bada0e15f61873ba6b2e29f4bb8b3ef2a489)
|
||||||
|
- #74 fixed a bug that caused a bunch of broken characters when non-ASCII input was given. Parser now handles UTF-8 input correctly. Other encodings are currently untested, UTF-8 is recommended.
|
||||||
|
|
||||||
|
Version 1.0.0 on 12. Oct. 2014
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
This is the first stable release of version 1.0 which is incompatible to the 0.9.x branch regarding the internal API which is used when extending the Markdown parser. The external API has no breaking changes. The rendered Markdown however has changed in some edge cases and some rendering issues have been fixed.
|
||||||
|
|
||||||
|
The parser got a bit slower compared to earlier versions but is able to parse Markdown more accurately and uses an abstract syntax tree as the internal representation of the parsed text which allows extensions to work with the parsed Markdown in many ways including rendering as other formats than HTML.
|
||||||
|
|
||||||
|
For more details about the changes see the [release message of 1.0.0-rc](https://github.com/cebe/markdown/releases/tag/1.0.0-rc).
|
||||||
|
|
||||||
|
You can try it out on the website: <http://markdown.cebe.cc/try>
|
||||||
|
|
||||||
|
The parser is now also regsitered on the [Babelmark 2 page](http://johnmacfarlane.net/babelmark2/?normalize=1&text=Hello+**World**!) by [John MacFarlane](http://johnmacfarlane.net/) which you can use to compare Markdown output of different parsers.
|
||||||
|
|
||||||
|
Version 1.0.0-rc on 10. Oct. 2014
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
- #21 speed up inline parsing using [strpbrk](http://www.php.net/manual/de/function.strpbrk.php) about 20% speedup compared to parsing before.
|
||||||
|
- #24 CLI script now sends all error output to stderr instead of stdout
|
||||||
|
- #25 Added partial support for the Markdown Extra flavor
|
||||||
|
- #10 GithubMarkdown is now fully supported including tables
|
||||||
|
- #67 All Markdown classes are now composed out of php traits
|
||||||
|
- #67 The way to extend markdown has changed due to the introduction of an abstract syntax tree. See https://github.com/cebe/markdown/commit/dd2d0faa71b630e982d6651476872469b927db6d for how it changes or read the new README.
|
||||||
|
- Introduced an abstract syntax tree as an intermediate representation between parsing steps.
|
||||||
|
This not only fixes some issues with nested block elements but also allows manipulation of the markdown
|
||||||
|
before rendering.
|
||||||
|
- This version also fixes serveral rendering issues.
|
||||||
|
|
||||||
|
Version 0.9.2 on 18. Feb. 2014
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
- #27 Fixed some rendering problems with block elements not separated by newlines
|
||||||
|
|
||||||
|
Version 0.9.1 on 18. Feb. 2014
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Fixed an issue with inline markers that begin with the same character e.g. `[` and `[[`.
|
||||||
|
|
||||||
|
Version 0.9.0 on 18. Feb. 2014
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The initial release.
|
||||||
|
|
||||||
|
- Complete implementation of the original Markdown spec
|
||||||
|
- GFM without tables
|
||||||
|
- a command line tool for markdown parsing
|
||||||
36
core/lib/composer/vendor/cebe/markdown/CONTRIBUTING.md
vendored
Normal file
36
core/lib/composer/vendor/cebe/markdown/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
Contributing
|
||||||
|
============
|
||||||
|
|
||||||
|
First of all, **thank you** for contributing, **you are awesome**! :)
|
||||||
|
|
||||||
|
If you have an idea or found a bug, please [open an issue](https://github.com/cebe/markdown/issues/new) on github.
|
||||||
|
|
||||||
|
If you want to contribute code, there a few rules to follow:
|
||||||
|
|
||||||
|
- I am following a code style that is basically [PSR-2](http://www.php-fig.org/psr/2/) but with TABS indentation (yes, I really do that ;) ).
|
||||||
|
I am not going to nit-pick on all the details about the code style but indentation is a must. The important part is that code is readable.
|
||||||
|
Methods should be documented using phpdoc style.
|
||||||
|
|
||||||
|
- All code must be covered by tests so if you fix a bug or add a feature, please include a test case for it. See below on how that works.
|
||||||
|
|
||||||
|
- If you add a feature it should be documented.
|
||||||
|
|
||||||
|
- Also, while creating your Pull Request on GitHub, please write a description
|
||||||
|
which gives the context and/or explains why you are creating it.
|
||||||
|
|
||||||
|
Thank you very much!
|
||||||
|
|
||||||
|
|
||||||
|
Running the tests
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The Markdown parser classes are tested with [PHPUnit](https://phpunit.de/). For each test case there is a set of files in
|
||||||
|
the subfolders of the `/tests` folder. The result of the parser is tested with an input and an output file respectively
|
||||||
|
where the input file contains the Markdown and the output file contains the expected HTML.
|
||||||
|
|
||||||
|
You can run the tests after initializing the lib with composer(`composer install`) with the following command:
|
||||||
|
|
||||||
|
vendor/bin/phpunit
|
||||||
|
|
||||||
|
To create a new test case, create a `.md` file a`.html` with the same base name in the subfolders of
|
||||||
|
the `/tests` directory. See existing files for examples.
|
||||||
114
core/lib/composer/vendor/cebe/markdown/GithubMarkdown.php
vendored
Normal file
114
core/lib/composer/vendor/cebe/markdown/GithubMarkdown.php
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Markdown parser for github flavored markdown.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
*/
|
||||||
|
class GithubMarkdown extends Markdown
|
||||||
|
{
|
||||||
|
// include block element parsing using traits
|
||||||
|
use block\TableTrait;
|
||||||
|
use block\FencedCodeTrait;
|
||||||
|
|
||||||
|
// include inline element parsing using traits
|
||||||
|
use inline\StrikeoutTrait;
|
||||||
|
use inline\UrlLinkTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean whether to interpret newlines as `<br />`-tags.
|
||||||
|
* This feature is useful for comments where newlines are often meant to be real new lines.
|
||||||
|
*/
|
||||||
|
public $enableNewlines = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected $escapeCharacters = [
|
||||||
|
// from Markdown
|
||||||
|
'\\', // backslash
|
||||||
|
'`', // backtick
|
||||||
|
'*', // asterisk
|
||||||
|
'_', // underscore
|
||||||
|
'{', '}', // curly braces
|
||||||
|
'[', ']', // square brackets
|
||||||
|
'(', ')', // parentheses
|
||||||
|
'#', // hash mark
|
||||||
|
'+', // plus sign
|
||||||
|
'-', // minus sign (hyphen)
|
||||||
|
'.', // dot
|
||||||
|
'!', // exclamation mark
|
||||||
|
'<', '>',
|
||||||
|
// added by GithubMarkdown
|
||||||
|
':', // colon
|
||||||
|
'|', // pipe
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a paragraph
|
||||||
|
*
|
||||||
|
* Allow headlines, lists and code to break paragraphs
|
||||||
|
*/
|
||||||
|
protected function consumeParagraph($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
$content = [];
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
if ($line === ''
|
||||||
|
|| ltrim($line) === ''
|
||||||
|
|| !ctype_alpha($line[0]) && (
|
||||||
|
$this->identifyQuote($line, $lines, $i) ||
|
||||||
|
$this->identifyFencedCode($line, $lines, $i) ||
|
||||||
|
$this->identifyUl($line, $lines, $i) ||
|
||||||
|
$this->identifyOl($line, $lines, $i) ||
|
||||||
|
$this->identifyHr($line, $lines, $i)
|
||||||
|
)
|
||||||
|
|| $this->identifyHeadline($line, $lines, $i))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
} elseif ($this->identifyCode($line, $lines, $i)) {
|
||||||
|
// possible beginning of a code block
|
||||||
|
// but check for continued inline HTML
|
||||||
|
// e.g. <img src="file.jpg"
|
||||||
|
// alt="some alt aligned with src attribute" title="some text" />
|
||||||
|
if (preg_match('~<\w+([^>]+)$~s', implode("\n", $content))) {
|
||||||
|
$content[] = $line;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$content[] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$block = [
|
||||||
|
'paragraph',
|
||||||
|
'content' => $this->parseInline(implode("\n", $content)),
|
||||||
|
];
|
||||||
|
return [$block, --$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdocs
|
||||||
|
*
|
||||||
|
* Parses a newline indicated by two spaces on the end of a markdown line.
|
||||||
|
*/
|
||||||
|
protected function renderText($text)
|
||||||
|
{
|
||||||
|
if ($this->enableNewlines) {
|
||||||
|
$br = $this->html5 ? "<br>\n" : "<br />\n";
|
||||||
|
return strtr($text[1], [" \n" => $br, "\n" => $br]);
|
||||||
|
} else {
|
||||||
|
return parent::renderText($text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
core/lib/composer/vendor/cebe/markdown/LICENSE
vendored
Normal file
21
core/lib/composer/vendor/cebe/markdown/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Carsten Brandt
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
128
core/lib/composer/vendor/cebe/markdown/Markdown.php
vendored
Normal file
128
core/lib/composer/vendor/cebe/markdown/Markdown.php
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Markdown parser for the [initial markdown spec](http://daringfireball.net/projects/markdown/syntax).
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
*/
|
||||||
|
class Markdown extends Parser
|
||||||
|
{
|
||||||
|
// include block element parsing using traits
|
||||||
|
use block\CodeTrait;
|
||||||
|
use block\HeadlineTrait;
|
||||||
|
use block\HtmlTrait {
|
||||||
|
parseInlineHtml as private;
|
||||||
|
}
|
||||||
|
use block\ListTrait {
|
||||||
|
// Check Ul List before headline
|
||||||
|
identifyUl as protected identifyBUl;
|
||||||
|
consumeUl as protected consumeBUl;
|
||||||
|
}
|
||||||
|
use block\QuoteTrait;
|
||||||
|
use block\RuleTrait {
|
||||||
|
// Check Hr before checking lists
|
||||||
|
identifyHr as protected identifyAHr;
|
||||||
|
consumeHr as protected consumeAHr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// include inline element parsing using traits
|
||||||
|
use inline\CodeTrait;
|
||||||
|
use inline\EmphStrongTrait;
|
||||||
|
use inline\LinkTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean whether to format markup according to HTML5 spec.
|
||||||
|
* Defaults to `false` which means that markup is formatted as HTML4.
|
||||||
|
*/
|
||||||
|
public $html5 = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array these are "escapeable" characters. When using one of these prefixed with a
|
||||||
|
* backslash, the character will be outputted without the backslash and is not interpreted
|
||||||
|
* as markdown.
|
||||||
|
*/
|
||||||
|
protected $escapeCharacters = [
|
||||||
|
'\\', // backslash
|
||||||
|
'`', // backtick
|
||||||
|
'*', // asterisk
|
||||||
|
'_', // underscore
|
||||||
|
'{', '}', // curly braces
|
||||||
|
'[', ']', // square brackets
|
||||||
|
'(', ')', // parentheses
|
||||||
|
'#', // hash mark
|
||||||
|
'+', // plus sign
|
||||||
|
'-', // minus sign (hyphen)
|
||||||
|
'.', // dot
|
||||||
|
'!', // exclamation mark
|
||||||
|
'<', '>',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected function prepare()
|
||||||
|
{
|
||||||
|
// reset references
|
||||||
|
$this->references = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a paragraph
|
||||||
|
*
|
||||||
|
* Allow headlines and code to break paragraphs
|
||||||
|
*/
|
||||||
|
protected function consumeParagraph($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
$content = [];
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
|
||||||
|
// a list may break a paragraph when it is inside of a list
|
||||||
|
if (isset($this->context[1]) && $this->context[1] === 'list' && !ctype_alpha($line[0]) && (
|
||||||
|
$this->identifyUl($line, $lines, $i) || $this->identifyOl($line, $lines, $i))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($line === '' || ltrim($line) === '' || $this->identifyHeadline($line, $lines, $i)) {
|
||||||
|
break;
|
||||||
|
} elseif ($line[0] === "\t" || $line[0] === " " && strncmp($line, ' ', 4) === 0) {
|
||||||
|
// possible beginning of a code block
|
||||||
|
// but check for continued inline HTML
|
||||||
|
// e.g. <img src="file.jpg"
|
||||||
|
// alt="some alt aligned with src attribute" title="some text" />
|
||||||
|
if (preg_match('~<\w+([^>]+)$~s', implode("\n", $content))) {
|
||||||
|
$content[] = $line;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$content[] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$block = [
|
||||||
|
'paragraph',
|
||||||
|
'content' => $this->parseInline(implode("\n", $content)),
|
||||||
|
];
|
||||||
|
return [$block, --$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdocs
|
||||||
|
*
|
||||||
|
* Parses a newline indicated by two spaces on the end of a markdown line.
|
||||||
|
*/
|
||||||
|
protected function renderText($text)
|
||||||
|
{
|
||||||
|
return str_replace(" \n", $this->html5 ? "<br>\n" : "<br />\n", $text[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
256
core/lib/composer/vendor/cebe/markdown/MarkdownExtra.php
vendored
Normal file
256
core/lib/composer/vendor/cebe/markdown/MarkdownExtra.php
vendored
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace cebe\markdown;
|
||||||
|
|
||||||
|
use cebe\markdown\block\TableTrait;
|
||||||
|
|
||||||
|
// work around https://github.com/facebook/hhvm/issues/1120
|
||||||
|
defined('ENT_HTML401') || define('ENT_HTML401', 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Markdown parser for the [markdown extra](http://michelf.ca/projects/php-markdown/extra/) flavor.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
class MarkdownExtra extends Markdown
|
||||||
|
{
|
||||||
|
// include block element parsing using traits
|
||||||
|
use block\TableTrait;
|
||||||
|
use block\FencedCodeTrait;
|
||||||
|
|
||||||
|
// include inline element parsing using traits
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether special attributes on code blocks should be applied on the `<pre>` element.
|
||||||
|
* The default behavior is to put them on the `<code>` element.
|
||||||
|
*/
|
||||||
|
public $codeAttributesOnPre = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
protected $escapeCharacters = [
|
||||||
|
// from Markdown
|
||||||
|
'\\', // backslash
|
||||||
|
'`', // backtick
|
||||||
|
'*', // asterisk
|
||||||
|
'_', // underscore
|
||||||
|
'{', '}', // curly braces
|
||||||
|
'[', ']', // square brackets
|
||||||
|
'(', ')', // parentheses
|
||||||
|
'#', // hash mark
|
||||||
|
'+', // plus sign
|
||||||
|
'-', // minus sign (hyphen)
|
||||||
|
'.', // dot
|
||||||
|
'!', // exclamation mark
|
||||||
|
'<', '>',
|
||||||
|
// added by MarkdownExtra
|
||||||
|
':', // colon
|
||||||
|
'|', // pipe
|
||||||
|
];
|
||||||
|
|
||||||
|
private $_specialAttributesRegex = '\{(([#\.][A-z0-9-_]+\s*)+)\}';
|
||||||
|
|
||||||
|
// TODO allow HTML intended 3 spaces
|
||||||
|
|
||||||
|
// TODO add markdown inside HTML blocks
|
||||||
|
|
||||||
|
// TODO implement definition lists
|
||||||
|
|
||||||
|
// TODO implement footnotes
|
||||||
|
|
||||||
|
// TODO implement Abbreviations
|
||||||
|
|
||||||
|
|
||||||
|
// block parsing
|
||||||
|
|
||||||
|
protected function identifyReference($line)
|
||||||
|
{
|
||||||
|
return ($line[0] === ' ' || $line[0] === '[') && preg_match('/^ {0,3}\[[^\[](.*?)\]:\s*([^\s]+?)(?:\s+[\'"](.+?)[\'"])?\s*('.$this->_specialAttributesRegex.')?\s*$/', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume link references
|
||||||
|
*/
|
||||||
|
protected function consumeReference($lines, $current)
|
||||||
|
{
|
||||||
|
while (isset($lines[$current]) && preg_match('/^ {0,3}\[(.+?)\]:\s*(.+?)(?:\s+[\(\'"](.+?)[\)\'"])?\s*('.$this->_specialAttributesRegex.')?\s*$/', $lines[$current], $matches)) {
|
||||||
|
$label = strtolower($matches[1]);
|
||||||
|
|
||||||
|
$this->references[$label] = [
|
||||||
|
'url' => $this->replaceEscape($matches[2]),
|
||||||
|
];
|
||||||
|
if (isset($matches[3])) {
|
||||||
|
$this->references[$label]['title'] = $matches[3];
|
||||||
|
} else {
|
||||||
|
// title may be on the next line
|
||||||
|
if (isset($lines[$current + 1]) && preg_match('/^\s+[\(\'"](.+?)[\)\'"]\s*$/', $lines[$current + 1], $matches)) {
|
||||||
|
$this->references[$label]['title'] = $matches[1];
|
||||||
|
$current++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($matches[5])) {
|
||||||
|
$this->references[$label]['attributes'] = $matches[5];
|
||||||
|
}
|
||||||
|
$current++;
|
||||||
|
}
|
||||||
|
return [false, --$current];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a fenced code block
|
||||||
|
*/
|
||||||
|
protected function consumeFencedCode($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until ```
|
||||||
|
$block = [
|
||||||
|
'code',
|
||||||
|
];
|
||||||
|
$line = trim($lines[$current]);
|
||||||
|
if (($pos = strrpos($line, '`')) === false) {
|
||||||
|
$pos = strrpos($line, '~');
|
||||||
|
}
|
||||||
|
$fence = substr($line, 0, $pos + 1);
|
||||||
|
$block['attributes'] = substr($line, $pos);
|
||||||
|
$content = [];
|
||||||
|
for($i = $current + 1, $count = count($lines); $i < $count; $i++) {
|
||||||
|
if (($pos = strpos($line = $lines[$i], $fence)) === false || $pos > 3) {
|
||||||
|
$content[] = $line;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$block['content'] = implode("\n", $content);
|
||||||
|
return [$block, $i];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderCode($block)
|
||||||
|
{
|
||||||
|
$attributes = $this->renderAttributes($block);
|
||||||
|
return ($this->codeAttributesOnPre ? "<pre$attributes><code>" : "<pre><code$attributes>")
|
||||||
|
. htmlspecialchars($block['content'] . "\n", ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8')
|
||||||
|
. "</code></pre>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a headline
|
||||||
|
*/
|
||||||
|
protected function renderHeadline($block)
|
||||||
|
{
|
||||||
|
foreach($block['content'] as $i => $element) {
|
||||||
|
if ($element[0] === 'specialAttributes') {
|
||||||
|
unset($block['content'][$i]);
|
||||||
|
$block['attributes'] = $element[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tag = 'h' . $block['level'];
|
||||||
|
$attributes = $this->renderAttributes($block);
|
||||||
|
return "<$tag$attributes>" . rtrim($this->renderAbsy($block['content']), "# \t") . "</$tag>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderAttributes($block)
|
||||||
|
{
|
||||||
|
$html = [];
|
||||||
|
if (isset($block['attributes'])) {
|
||||||
|
$attributes = preg_split('/\s+/', $block['attributes'], -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
foreach($attributes as $attribute) {
|
||||||
|
if ($attribute[0] === '#') {
|
||||||
|
$html['id'] = substr($attribute, 1);
|
||||||
|
} else {
|
||||||
|
$html['class'][] = substr($attribute, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = '';
|
||||||
|
foreach($html as $attr => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$value = trim(implode(' ', $value));
|
||||||
|
}
|
||||||
|
if (!empty($value)) {
|
||||||
|
$result .= " $attr=\"$value\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// inline parsing
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @marker {
|
||||||
|
*/
|
||||||
|
protected function parseSpecialAttributes($text)
|
||||||
|
{
|
||||||
|
if (preg_match("~$this->_specialAttributesRegex~", $text, $matches)) {
|
||||||
|
return [['specialAttributes', $matches[1]], strlen($matches[0])];
|
||||||
|
}
|
||||||
|
return [['text', '{'], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderSpecialAttributes($block)
|
||||||
|
{
|
||||||
|
return '{' . $block[1] . '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseInline($text)
|
||||||
|
{
|
||||||
|
$elements = parent::parseInline($text);
|
||||||
|
// merge special attribute elements to links and images as they are not part of the final absy later
|
||||||
|
$relatedElement = null;
|
||||||
|
foreach($elements as $i => $element) {
|
||||||
|
if ($element[0] === 'link' || $element[0] === 'image') {
|
||||||
|
$relatedElement = $i;
|
||||||
|
} elseif ($element[0] === 'specialAttributes') {
|
||||||
|
if ($relatedElement !== null) {
|
||||||
|
$elements[$relatedElement]['attributes'] = $element[1];
|
||||||
|
unset($elements[$i]);
|
||||||
|
}
|
||||||
|
$relatedElement = null;
|
||||||
|
} else {
|
||||||
|
$relatedElement = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderLink($block)
|
||||||
|
{
|
||||||
|
if (isset($block['refkey'])) {
|
||||||
|
if (($ref = $this->lookupReference($block['refkey'])) !== false) {
|
||||||
|
$block = array_merge($block, $ref);
|
||||||
|
} else {
|
||||||
|
if (strncmp($block['orig'], '[', 1) === 0) {
|
||||||
|
return '[' . $this->renderAbsy($this->parseInline(substr($block['orig'], 1)));
|
||||||
|
}
|
||||||
|
return $block['orig'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$attributes = $this->renderAttributes($block);
|
||||||
|
return '<a href="' . htmlspecialchars($block['url'], ENT_COMPAT | ENT_HTML401, 'UTF-8') . '"'
|
||||||
|
. (empty($block['title']) ? '' : ' title="' . htmlspecialchars($block['title'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE, 'UTF-8') . '"')
|
||||||
|
. $attributes . '>' . $this->renderAbsy($block['text']) . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderImage($block)
|
||||||
|
{
|
||||||
|
if (isset($block['refkey'])) {
|
||||||
|
if (($ref = $this->lookupReference($block['refkey'])) !== false) {
|
||||||
|
$block = array_merge($block, $ref);
|
||||||
|
} else {
|
||||||
|
if (strncmp($block['orig'], '![', 2) === 0) {
|
||||||
|
return '![' . $this->renderAbsy($this->parseInline(substr($block['orig'], 2)));
|
||||||
|
}
|
||||||
|
return $block['orig'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$attributes = $this->renderAttributes($block);
|
||||||
|
return '<img src="' . htmlspecialchars($block['url'], ENT_COMPAT | ENT_HTML401, 'UTF-8') . '"'
|
||||||
|
. ' alt="' . htmlspecialchars($block['text'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE, 'UTF-8') . '"'
|
||||||
|
. (empty($block['title']) ? '' : ' title="' . htmlspecialchars($block['title'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE, 'UTF-8') . '"')
|
||||||
|
. $attributes . ($this->html5 ? '>' : ' />');
|
||||||
|
}
|
||||||
|
}
|
||||||
389
core/lib/composer/vendor/cebe/markdown/Parser.php
vendored
Normal file
389
core/lib/composer/vendor/cebe/markdown/Parser.php
vendored
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown;
|
||||||
|
use ReflectionMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic parser for markdown-like languages.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
*/
|
||||||
|
abstract class Parser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var integer the maximum nesting level for language elements.
|
||||||
|
*/
|
||||||
|
public $maximumNestingLevel = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array the current context the parser is in.
|
||||||
|
* TODO remove in favor of absy
|
||||||
|
*/
|
||||||
|
protected $context = [];
|
||||||
|
/**
|
||||||
|
* @var array these are "escapeable" characters. When using one of these prefixed with a
|
||||||
|
* backslash, the character will be outputted without the backslash and is not interpreted
|
||||||
|
* as markdown.
|
||||||
|
*/
|
||||||
|
protected $escapeCharacters = [
|
||||||
|
'\\', // backslash
|
||||||
|
];
|
||||||
|
|
||||||
|
private $_depth = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given text considering the full language.
|
||||||
|
*
|
||||||
|
* This includes parsing block elements as well as inline elements.
|
||||||
|
*
|
||||||
|
* @param string $text the text to parse
|
||||||
|
* @return string parsed markup
|
||||||
|
*/
|
||||||
|
public function parse($text)
|
||||||
|
{
|
||||||
|
$this->prepare();
|
||||||
|
|
||||||
|
if (ltrim($text) === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = str_replace(["\r\n", "\n\r", "\r"], "\n", $text);
|
||||||
|
|
||||||
|
$this->prepareMarkers($text);
|
||||||
|
|
||||||
|
$absy = $this->parseBlocks(explode("\n", $text));
|
||||||
|
$markup = $this->renderAbsy($absy);
|
||||||
|
|
||||||
|
$this->cleanup();
|
||||||
|
return $markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a paragraph without block elements (block elements are ignored).
|
||||||
|
*
|
||||||
|
* @param string $text the text to parse
|
||||||
|
* @return string parsed markup
|
||||||
|
*/
|
||||||
|
public function parseParagraph($text)
|
||||||
|
{
|
||||||
|
$this->prepare();
|
||||||
|
|
||||||
|
if (ltrim($text) === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = str_replace(["\r\n", "\n\r", "\r"], "\n", $text);
|
||||||
|
|
||||||
|
$this->prepareMarkers($text);
|
||||||
|
|
||||||
|
$absy = $this->parseInline($text);
|
||||||
|
$markup = $this->renderAbsy($absy);
|
||||||
|
|
||||||
|
$this->cleanup();
|
||||||
|
return $markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be called before `parse()` and `parseParagraph()`.
|
||||||
|
* You can override it to do some initialization work.
|
||||||
|
*/
|
||||||
|
protected function prepare()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be called after `parse()` and `parseParagraph()`.
|
||||||
|
* You can override it to do cleanup.
|
||||||
|
*/
|
||||||
|
protected function cleanup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// block parsing
|
||||||
|
|
||||||
|
private $_blockTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array a list of block element types available.
|
||||||
|
*/
|
||||||
|
protected function blockTypes()
|
||||||
|
{
|
||||||
|
if ($this->_blockTypes === null) {
|
||||||
|
// detect block types via "identify" functions
|
||||||
|
$reflection = new \ReflectionClass($this);
|
||||||
|
$this->_blockTypes = array_filter(array_map(function($method) {
|
||||||
|
$name = $method->getName();
|
||||||
|
return strncmp($name, 'identify', 8) === 0 ? strtolower(substr($name, 8)) : false;
|
||||||
|
}, $reflection->getMethods(ReflectionMethod::IS_PROTECTED)));
|
||||||
|
|
||||||
|
sort($this->_blockTypes);
|
||||||
|
}
|
||||||
|
return $this->_blockTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a set of lines and an index of a current line it uses the registed block types to
|
||||||
|
* detect the type of this line.
|
||||||
|
* @param array $lines
|
||||||
|
* @param integer $current
|
||||||
|
* @return string name of the block type in lower case
|
||||||
|
*/
|
||||||
|
protected function detectLineType($lines, $current)
|
||||||
|
{
|
||||||
|
$line = $lines[$current];
|
||||||
|
$blockTypes = $this->blockTypes();
|
||||||
|
foreach($blockTypes as $blockType) {
|
||||||
|
if ($this->{'identify' . $blockType}($line, $lines, $current)) {
|
||||||
|
return $blockType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// consider the line a normal paragraph if no other block type matches
|
||||||
|
return 'paragraph';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse block elements by calling `detectLineType()` to identify them
|
||||||
|
* and call consume function afterwards.
|
||||||
|
*/
|
||||||
|
protected function parseBlocks($lines)
|
||||||
|
{
|
||||||
|
if ($this->_depth >= $this->maximumNestingLevel) {
|
||||||
|
// maximum depth is reached, do not parse input
|
||||||
|
return [['text', implode("\n", $lines)]];
|
||||||
|
}
|
||||||
|
$this->_depth++;
|
||||||
|
|
||||||
|
$blocks = [];
|
||||||
|
|
||||||
|
// convert lines to blocks
|
||||||
|
for ($i = 0, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
if ($line !== '' && rtrim($line) !== '') { // skip empty lines
|
||||||
|
// identify a blocks beginning and parse the content
|
||||||
|
list($block, $i) = $this->parseBlock($lines, $i);
|
||||||
|
if ($block !== false) {
|
||||||
|
$blocks[] = $block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_depth--;
|
||||||
|
|
||||||
|
return $blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the block at current line by identifying the block type and parsing the content
|
||||||
|
* @param $lines
|
||||||
|
* @param $current
|
||||||
|
* @return array Array of two elements, the first element contains the block,
|
||||||
|
* the second contains the next line index to be parsed.
|
||||||
|
*/
|
||||||
|
protected function parseBlock($lines, $current)
|
||||||
|
{
|
||||||
|
// identify block type for this line
|
||||||
|
$blockType = $this->detectLineType($lines, $current);
|
||||||
|
|
||||||
|
// call consume method for the detected block type to consume further lines
|
||||||
|
return $this->{'consume' . $blockType}($lines, $current);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderAbsy($blocks)
|
||||||
|
{
|
||||||
|
$output = '';
|
||||||
|
foreach ($blocks as $block) {
|
||||||
|
array_unshift($this->context, $block[0]);
|
||||||
|
$output .= $this->{'render' . $block[0]}($block);
|
||||||
|
array_shift($this->context);
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a paragraph
|
||||||
|
*
|
||||||
|
* @param $lines
|
||||||
|
* @param $current
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function consumeParagraph($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
$content = [];
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
if (ltrim($lines[$i]) !== '') {
|
||||||
|
$content[] = $lines[$i];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$block = [
|
||||||
|
'paragraph',
|
||||||
|
'content' => $this->parseInline(implode("\n", $content)),
|
||||||
|
];
|
||||||
|
return [$block, --$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a paragraph block
|
||||||
|
*
|
||||||
|
* @param $block
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function renderParagraph($block)
|
||||||
|
{
|
||||||
|
return '<p>' . $this->renderAbsy($block['content']) . "</p>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// inline parsing
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array the set of inline markers to use in different contexts.
|
||||||
|
*/
|
||||||
|
private $_inlineMarkers = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map of inline markers to the corresponding parser methods.
|
||||||
|
*
|
||||||
|
* This array defines handler methods for inline markdown markers.
|
||||||
|
* When a marker is found in the text, the handler method is called with the text
|
||||||
|
* starting at the position of the marker.
|
||||||
|
*
|
||||||
|
* Note that markers starting with whitespace may slow down the parser,
|
||||||
|
* you may want to use [[renderText]] to deal with them.
|
||||||
|
*
|
||||||
|
* You may override this method to define a set of markers and parsing methods.
|
||||||
|
* The default implementation looks for protected methods starting with `parse` that
|
||||||
|
* also have an `@marker` annotation in PHPDoc.
|
||||||
|
*
|
||||||
|
* @return array a map of markers to parser methods
|
||||||
|
*/
|
||||||
|
protected function inlineMarkers()
|
||||||
|
{
|
||||||
|
$markers = [];
|
||||||
|
// detect "parse" functions
|
||||||
|
$reflection = new \ReflectionClass($this);
|
||||||
|
foreach($reflection->getMethods(ReflectionMethod::IS_PROTECTED) as $method) {
|
||||||
|
$methodName = $method->getName();
|
||||||
|
if (strncmp($methodName, 'parse', 5) === 0) {
|
||||||
|
preg_match_all('/@marker ([^\s]+)/', $method->getDocComment(), $matches);
|
||||||
|
foreach($matches[1] as $match) {
|
||||||
|
$markers[$match] = $methodName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare markers that are used in the text to parse
|
||||||
|
*
|
||||||
|
* Add all markers that are present in markdown.
|
||||||
|
* Check is done to avoid iterations in parseInline(), good for huge markdown files
|
||||||
|
* @param string $text
|
||||||
|
*/
|
||||||
|
protected function prepareMarkers($text)
|
||||||
|
{
|
||||||
|
$this->_inlineMarkers = [];
|
||||||
|
foreach ($this->inlineMarkers() as $marker => $method) {
|
||||||
|
if (strpos($text, $marker) !== false) {
|
||||||
|
$m = $marker[0];
|
||||||
|
// put the longest marker first
|
||||||
|
if (isset($this->_inlineMarkers[$m])) {
|
||||||
|
reset($this->_inlineMarkers[$m]);
|
||||||
|
if (strlen($marker) > strlen(key($this->_inlineMarkers[$m]))) {
|
||||||
|
$this->_inlineMarkers[$m] = array_merge([$marker => $method], $this->_inlineMarkers[$m]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_inlineMarkers[$m][$marker] = $method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses inline elements of the language.
|
||||||
|
*
|
||||||
|
* @param string $text the inline text to parse.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function parseInline($text)
|
||||||
|
{
|
||||||
|
if ($this->_depth >= $this->maximumNestingLevel) {
|
||||||
|
// maximum depth is reached, do not parse input
|
||||||
|
return [['text', $text]];
|
||||||
|
}
|
||||||
|
$this->_depth++;
|
||||||
|
|
||||||
|
$markers = implode('', array_keys($this->_inlineMarkers));
|
||||||
|
|
||||||
|
$paragraph = [];
|
||||||
|
|
||||||
|
while (!empty($markers) && ($found = strpbrk($text, $markers)) !== false) {
|
||||||
|
|
||||||
|
$pos = strpos($text, $found);
|
||||||
|
|
||||||
|
// add the text up to next marker to the paragraph
|
||||||
|
if ($pos !== 0) {
|
||||||
|
$paragraph[] = ['text', substr($text, 0, $pos)];
|
||||||
|
}
|
||||||
|
$text = $found;
|
||||||
|
|
||||||
|
$parsed = false;
|
||||||
|
foreach ($this->_inlineMarkers[$text[0]] as $marker => $method) {
|
||||||
|
if (strncmp($text, $marker, strlen($marker)) === 0) {
|
||||||
|
// parse the marker
|
||||||
|
array_unshift($this->context, $method);
|
||||||
|
list($output, $offset) = $this->$method($text);
|
||||||
|
array_shift($this->context);
|
||||||
|
|
||||||
|
$paragraph[] = $output;
|
||||||
|
$text = substr($text, $offset);
|
||||||
|
$parsed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$parsed) {
|
||||||
|
$paragraph[] = ['text', substr($text, 0, 1)];
|
||||||
|
$text = substr($text, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$paragraph[] = ['text', $text];
|
||||||
|
|
||||||
|
$this->_depth--;
|
||||||
|
|
||||||
|
return $paragraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses escaped special characters.
|
||||||
|
* @marker \
|
||||||
|
*/
|
||||||
|
protected function parseEscape($text)
|
||||||
|
{
|
||||||
|
if (isset($text[1]) && in_array($text[1], $this->escapeCharacters)) {
|
||||||
|
return [['text', $text[1]], 2];
|
||||||
|
}
|
||||||
|
return [['text', $text[0]], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function renders plain text sections in the markdown text.
|
||||||
|
* It can be used to work on normal text sections for example to highlight keywords or
|
||||||
|
* do special escaping.
|
||||||
|
*/
|
||||||
|
protected function renderText($block)
|
||||||
|
{
|
||||||
|
return $block[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
521
core/lib/composer/vendor/cebe/markdown/README.md
vendored
Normal file
521
core/lib/composer/vendor/cebe/markdown/README.md
vendored
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
A super fast, highly extensible markdown parser for PHP
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
[](https://packagist.org/packages/cebe/markdown)
|
||||||
|
[](https://packagist.org/packages/cebe/markdown)
|
||||||
|
[](http://travis-ci.org/cebe/markdown)
|
||||||
|
[](https://scrutinizer-ci.com/g/cebe/markdown/)
|
||||||
|
[](https://scrutinizer-ci.com/g/cebe/markdown/)
|
||||||
|
|
||||||
|
What is this? <a name="what"></a>
|
||||||
|
-------------
|
||||||
|
|
||||||
|
A set of [PHP][] classes, each representing a [Markdown][] flavor, and a command line tool
|
||||||
|
for converting markdown files to HTML files.
|
||||||
|
|
||||||
|
The implementation focus is to be **fast** (see [benchmark][]) and **extensible**.
|
||||||
|
Parsing Markdown to HTML is as simple as calling a single method (see [Usage](#usage)) providing a solid implementation
|
||||||
|
that gives most expected results even in non-trivial edge cases.
|
||||||
|
|
||||||
|
Extending the Markdown language with new elements is as simple as adding a new method to the class that converts the
|
||||||
|
markdown text to the expected output in HTML. This is possible without dealing with complex and error prone regular expressions.
|
||||||
|
It is also possible to hook into the markdown structure and add elements or read meta information using the internal representation
|
||||||
|
of the Markdown text as an abstract syntax tree (see [Extending the language](#extend)).
|
||||||
|
|
||||||
|
Currently the following markdown flavors are supported:
|
||||||
|
|
||||||
|
- **Traditional Markdown** according to <http://daringfireball.net/projects/markdown/syntax> ([try it!](http://markdown.cebe.cc/try?flavor=default)).
|
||||||
|
- **Github flavored Markdown** according to <https://help.github.com/articles/github-flavored-markdown> ([try it!](http://markdown.cebe.cc/try?flavor=gfm)).
|
||||||
|
- **Markdown Extra** according to <http://michelf.ca/projects/php-markdown/extra/> (currently not fully supported WIP see [#25][], [try it!](http://markdown.cebe.cc/try?flavor=extra))
|
||||||
|
- Any mixed Markdown flavor you like because of its highly extensible structure (See documentation below).
|
||||||
|
|
||||||
|
Future plans are to support:
|
||||||
|
|
||||||
|
- Smarty Pants <http://daringfireball.net/projects/smartypants/>
|
||||||
|
- ... (Feel free to [suggest](https://github.com/cebe/markdown/issues/new) further additions!)
|
||||||
|
|
||||||
|
[PHP]: http://php.net/ "PHP is a popular general-purpose scripting language that is especially suited to web development."
|
||||||
|
[Markdown]: http://en.wikipedia.org/wiki/Markdown "Markdown on Wikipedia"
|
||||||
|
[#25]: https://github.com/cebe/markdown/issues/25 "issue #25"
|
||||||
|
[benchmark]: https://github.com/kzykhys/Markbench#readme "kzykhys/Markbench on github"
|
||||||
|
|
||||||
|
### Who is using it?
|
||||||
|
|
||||||
|
- It powers the [API-docs and the definitive guide](http://www.yiiframework.com/doc-2.0/) for the [Yii Framework][] [2.0](https://github.com/yiisoft/yii2).
|
||||||
|
|
||||||
|
[Yii Framework]: http://www.yiiframework.com/ "The Yii PHP Framework"
|
||||||
|
|
||||||
|
|
||||||
|
Installation <a name="installation"></a>
|
||||||
|
------------
|
||||||
|
|
||||||
|
[PHP 5.4 or higher](http://www.php.net/downloads.php) is required to use it.
|
||||||
|
It will also run on facebook's [hhvm](http://hhvm.com/).
|
||||||
|
|
||||||
|
The library uses PHPDoc annotations to determine the markdown elements that should be parsed.
|
||||||
|
So in case you are using PHP `opcache`, make sure
|
||||||
|
[it does not strip comments](http://php.net/manual/en/opcache.configuration.php#ini.opcache.save-comments).
|
||||||
|
|
||||||
|
Installation is recommended to be done via [composer][] by running:
|
||||||
|
|
||||||
|
composer require cebe/markdown "~1.2.0"
|
||||||
|
|
||||||
|
Alternatively you can add the following to the `require` section in your `composer.json` manually:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"cebe/markdown": "~1.2.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `composer update` afterwards.
|
||||||
|
|
||||||
|
[composer]: https://getcomposer.org/ "The PHP package manager"
|
||||||
|
|
||||||
|
> Note: If you have configured PHP with opcache you need to enable the
|
||||||
|
> [opcache.save_comments](http://php.net/manual/en/opcache.configuration.php#ini.opcache.save-comments) option because inline element parsing relies on PHPdoc annotations to find declared elements.
|
||||||
|
|
||||||
|
Usage <a name="usage"></a>
|
||||||
|
-----
|
||||||
|
|
||||||
|
### In your PHP project
|
||||||
|
|
||||||
|
To parse your markdown you need only two lines of code. The first one is to choose the markdown flavor as
|
||||||
|
one of the following:
|
||||||
|
|
||||||
|
- Traditional Markdown: `$parser = new \cebe\markdown\Markdown();`
|
||||||
|
- Github Flavored Markdown: `$parser = new \cebe\markdown\GithubMarkdown();`
|
||||||
|
- Markdown Extra: `$parser = new \cebe\markdown\MarkdownExtra();`
|
||||||
|
|
||||||
|
The next step is to call the `parse()`-method for parsing the text using the full markdown language
|
||||||
|
or calling the `parseParagraph()`-method to parse only inline elements.
|
||||||
|
|
||||||
|
Here are some examples:
|
||||||
|
|
||||||
|
```php
|
||||||
|
// traditional markdown and parse full text
|
||||||
|
$parser = new \cebe\markdown\Markdown();
|
||||||
|
echo $parser->parse($markdown);
|
||||||
|
|
||||||
|
// use github markdown
|
||||||
|
$parser = new \cebe\markdown\GithubMarkdown();
|
||||||
|
echo $parser->parse($markdown);
|
||||||
|
|
||||||
|
// use markdown extra
|
||||||
|
$parser = new \cebe\markdown\MarkdownExtra();
|
||||||
|
echo $parser->parse($markdown);
|
||||||
|
|
||||||
|
// parse only inline elements (useful for one-line descriptions)
|
||||||
|
$parser = new \cebe\markdown\GithubMarkdown();
|
||||||
|
echo $parser->parseParagraph($markdown);
|
||||||
|
```
|
||||||
|
|
||||||
|
You may optionally set one of the following options on the parser object:
|
||||||
|
|
||||||
|
For all Markdown Flavors:
|
||||||
|
|
||||||
|
- `$parser->html5 = true` to enable HTML5 output instead of HTML4.
|
||||||
|
- `$parser->keepListStartNumber = true` to enable keeping the numbers of ordered lists as specified in the markdown.
|
||||||
|
The default behavior is to always start from 1 and increment by one regardless of the number in markdown.
|
||||||
|
|
||||||
|
For GithubMarkdown:
|
||||||
|
|
||||||
|
- `$parser->enableNewlines = true` to convert all newlines to `<br/>`-tags. By default only newlines with two preceding spaces are converted to `<br/>`-tags.
|
||||||
|
|
||||||
|
It is recommended to use UTF-8 encoding for the input strings. Other encodings may work, but are currently untested.
|
||||||
|
|
||||||
|
### The command line script
|
||||||
|
|
||||||
|
You can use it to render this readme:
|
||||||
|
|
||||||
|
bin/markdown README.md > README.html
|
||||||
|
|
||||||
|
Using github flavored markdown:
|
||||||
|
|
||||||
|
bin/markdown --flavor=gfm README.md > README.html
|
||||||
|
|
||||||
|
or convert the original markdown description to html using the unix pipe:
|
||||||
|
|
||||||
|
curl http://daringfireball.net/projects/markdown/syntax.text | bin/markdown > md.html
|
||||||
|
|
||||||
|
Here is the full Help output you will see when running `bin/markdown --help`:
|
||||||
|
|
||||||
|
PHP Markdown to HTML converter
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
by Carsten Brandt <mail@cebe.cc>
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
bin/markdown [--flavor=<flavor>] [--full] [file.md]
|
||||||
|
|
||||||
|
--flavor specifies the markdown flavor to use. If omitted the original markdown by John Gruber [1] will be used.
|
||||||
|
Available flavors:
|
||||||
|
|
||||||
|
gfm - Github flavored markdown [2]
|
||||||
|
extra - Markdown Extra [3]
|
||||||
|
|
||||||
|
--full ouput a full HTML page with head and body. If not given, only the parsed markdown will be output.
|
||||||
|
|
||||||
|
--help shows this usage information.
|
||||||
|
|
||||||
|
If no file is specified input will be read from STDIN.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Render a file with original markdown:
|
||||||
|
|
||||||
|
bin/markdown README.md > README.html
|
||||||
|
|
||||||
|
Render a file using gihtub flavored markdown:
|
||||||
|
|
||||||
|
bin/markdown --flavor=gfm README.md > README.html
|
||||||
|
|
||||||
|
Convert the original markdown description to html using STDIN:
|
||||||
|
|
||||||
|
curl http://daringfireball.net/projects/markdown/syntax.text | bin/markdown > md.html
|
||||||
|
|
||||||
|
|
||||||
|
[1] http://daringfireball.net/projects/markdown/syntax
|
||||||
|
[2] https://help.github.com/articles/github-flavored-markdown
|
||||||
|
[3] http://michelf.ca/projects/php-markdown/extra/
|
||||||
|
|
||||||
|
|
||||||
|
Extensions
|
||||||
|
----------
|
||||||
|
|
||||||
|
Here are some extensions to this library:
|
||||||
|
|
||||||
|
- [Bogardo/markdown-codepen](https://github.com/Bogardo/markdown-codepen) - shortcode to embed codepens from http://codepen.io/ in markdown.
|
||||||
|
- [kartik-v/yii2-markdown](https://github.com/kartik-v/yii2-markdown) - Advanced Markdown editing and conversion utilities for Yii Framework 2.0.
|
||||||
|
- [cebe/markdown-latex](https://github.com/cebe/markdown-latex) - Convert Markdown to LaTeX and PDF
|
||||||
|
- [softark/creole](https://github.com/softark/creole) - A creole markup parser
|
||||||
|
- [hyn/frontmatter](https://github.com/hyn/frontmatter) - Frontmatter Metadata Support (JSON, TOML, YAML)
|
||||||
|
- ... [add yours!](https://github.com/cebe/markdown/edit/master/README.md#L186)
|
||||||
|
|
||||||
|
|
||||||
|
Extending the language <a name="extend"></a>
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Markdown consists of two types of language elements, I'll call them block and inline elements simlar to what you have in
|
||||||
|
HTML with `<div>` and `<span>`. Block elements are normally spreads over several lines and are separated by blank lines.
|
||||||
|
The most basic block element is a paragraph (`<p>`).
|
||||||
|
Inline elements are elements that are added inside of block elements i.e. inside of text.
|
||||||
|
|
||||||
|
This markdown parser allows you to extend the markdown language by changing existing elements behavior and also adding
|
||||||
|
new block and inline elements. You do this by extending from the parser class and adding/overriding class methods and
|
||||||
|
properties. For the different element types there are different ways to extend them as you will see in the following sections.
|
||||||
|
|
||||||
|
### Adding block elements
|
||||||
|
|
||||||
|
The markdown is parsed line by line to identify each non-empty line as one of the block element types.
|
||||||
|
To identify a line as the beginning of a block element it calls all protected class methods who's name begins with `identify`.
|
||||||
|
An identify function returns true if it has identified the block element it is responsible for or false if not.
|
||||||
|
In the following example we will implement support for [fenced code blocks][] which are part of the github flavored markdown.
|
||||||
|
|
||||||
|
[fenced code blocks]: https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks
|
||||||
|
"Fenced code block feature of github flavored markdown"
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class MyMarkdown extends \cebe\markdown\Markdown
|
||||||
|
{
|
||||||
|
protected function identifyFencedCode($line, $lines, $current)
|
||||||
|
{
|
||||||
|
// if a line starts with at least 3 backticks it is identified as a fenced code block
|
||||||
|
if (strncmp($line, '```', 3) === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above, `$line` is a string containing the content of the current line and is equal to `$lines[$current]`.
|
||||||
|
You may use `$lines` and `$current` to check other lines than the current line. In most cases you can ignore these parameters.
|
||||||
|
|
||||||
|
Parsing of a block element is done in two steps:
|
||||||
|
|
||||||
|
1. **Consuming** all the lines belonging to it. In most cases this is iterating over the lines starting from the identified
|
||||||
|
line until a blank line occurs. This step is implemented by a method named `consume{blockName}()` where `{blockName}`
|
||||||
|
is the same name as used for the identify function above. The consume method also takes the lines array
|
||||||
|
and the number of the current line. It will return two arguments: an array representing the block element in the abstract syntax tree
|
||||||
|
of the markdown document and the line number to parse next. In the abstract syntax array the first element refers to the name of
|
||||||
|
the element, all other array elements can be freely defined by yourself.
|
||||||
|
In our example we will implement it like this:
|
||||||
|
|
||||||
|
```php
|
||||||
|
protected function consumeFencedCode($lines, $current)
|
||||||
|
{
|
||||||
|
// create block array
|
||||||
|
$block = [
|
||||||
|
'fencedCode',
|
||||||
|
'content' => [],
|
||||||
|
];
|
||||||
|
$line = rtrim($lines[$current]);
|
||||||
|
|
||||||
|
// detect language and fence length (can be more than 3 backticks)
|
||||||
|
$fence = substr($line, 0, $pos = strrpos($line, '`') + 1);
|
||||||
|
$language = substr($line, $pos);
|
||||||
|
if (!empty($language)) {
|
||||||
|
$block['language'] = $language;
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume all lines until ```
|
||||||
|
for($i = $current + 1, $count = count($lines); $i < $count; $i++) {
|
||||||
|
if (rtrim($line = $lines[$i]) !== $fence) {
|
||||||
|
$block['content'][] = $line;
|
||||||
|
} else {
|
||||||
|
// stop consuming when code block is over
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [$block, $i];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Rendering** the element. After all blocks have been consumed, they are being rendered using the
|
||||||
|
`render{elementName}()`-method where `elementName` refers to the name of the element in the abstract syntax tree:
|
||||||
|
|
||||||
|
```php
|
||||||
|
protected function renderFencedCode($block)
|
||||||
|
{
|
||||||
|
$class = isset($block['language']) ? ' class="language-' . $block['language'] . '"' : '';
|
||||||
|
return "<pre><code$class>" . htmlspecialchars(implode("\n", $block['content']) . "\n", ENT_NOQUOTES, 'UTF-8') . '</code></pre>';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You may also add code highlighting here. In general it would also be possible to render ouput in a different language than
|
||||||
|
HTML for example LaTeX.
|
||||||
|
|
||||||
|
|
||||||
|
### Adding inline elements
|
||||||
|
|
||||||
|
Adding inline elements is different from block elements as they are parsed using markers in the text.
|
||||||
|
An inline element is identified by a marker that marks the beginning of an inline element (e.g. `[` will mark a possible
|
||||||
|
beginning of a link or `` ` `` will mark inline code).
|
||||||
|
|
||||||
|
Parsing methods for inline elements are also protected and identified by the prefix `parse`. Additionally a `@marker` annotation
|
||||||
|
in PHPDoc is needed to register the parse function for one or multiple markers.
|
||||||
|
The method will then be called when a marker is found in the text. As an argument it takes the text starting at the position of the marker.
|
||||||
|
The parser method will return an array containing the element of the abstract sytnax tree and an offset of text it has
|
||||||
|
parsed from the input markdown. All text up to this offset will be removed from the markdown before the next marker will be searched.
|
||||||
|
|
||||||
|
As an example, we will add support for the [strikethrough][] feature of github flavored markdown:
|
||||||
|
|
||||||
|
[strikethrough]: https://help.github.com/articles/github-flavored-markdown#strikethrough "Strikethrough feature of github flavored markdown"
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class MyMarkdown extends \cebe\markdown\Markdown
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @marker ~~
|
||||||
|
*/
|
||||||
|
protected function parseStrike($markdown)
|
||||||
|
{
|
||||||
|
// check whether the marker really represents a strikethrough (i.e. there is a closing ~~)
|
||||||
|
if (preg_match('/^~~(.+?)~~/', $markdown, $matches)) {
|
||||||
|
return [
|
||||||
|
// return the parsed tag as an element of the abstract syntax tree and call `parseInline()` to allow
|
||||||
|
// other inline markdown elements inside this tag
|
||||||
|
['strike', $this->parseInline($matches[1])],
|
||||||
|
// return the offset of the parsed text
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// in case we did not find a closing ~~ we just return the marker and skip 2 characters
|
||||||
|
return [['text', '~~'], 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// rendering is the same as for block elements, we turn the abstract syntax array into a string.
|
||||||
|
protected function renderStrike($element)
|
||||||
|
{
|
||||||
|
return '<del>' . $this->renderAbsy($element[1]) . '</del>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Composing your own Markdown flavor
|
||||||
|
|
||||||
|
This markdown library is composed of traits so it is very easy to create your own markdown flavor by adding and/or removing
|
||||||
|
the single feature traits.
|
||||||
|
|
||||||
|
Designing your Markdown flavor consists of four steps:
|
||||||
|
|
||||||
|
1. Select a base class
|
||||||
|
2. Select language feature traits
|
||||||
|
3. Define escapeable characters
|
||||||
|
4. Optionally add custom rendering behavior
|
||||||
|
|
||||||
|
#### Select a base class
|
||||||
|
|
||||||
|
If you want to extend from a flavor and only add features you can use one of the existing classes
|
||||||
|
(`Markdown`, `GithubMarkdown` or `MarkdownExtra`) as your flavors base class.
|
||||||
|
|
||||||
|
If you want to define a subset of the markdown language, i.e. remove some of the features, you have to
|
||||||
|
extend your class from `Parser`.
|
||||||
|
|
||||||
|
#### Select language feature traits
|
||||||
|
|
||||||
|
The following shows the trait selection for traditional Markdown.
|
||||||
|
|
||||||
|
```php
|
||||||
|
class MyMarkdown extends Parser
|
||||||
|
{
|
||||||
|
// include block element parsing using traits
|
||||||
|
use block\CodeTrait;
|
||||||
|
use block\HeadlineTrait;
|
||||||
|
use block\HtmlTrait {
|
||||||
|
parseInlineHtml as private;
|
||||||
|
}
|
||||||
|
use block\ListTrait {
|
||||||
|
// Check Ul List before headline
|
||||||
|
identifyUl as protected identifyBUl;
|
||||||
|
consumeUl as protected consumeBUl;
|
||||||
|
}
|
||||||
|
use block\QuoteTrait;
|
||||||
|
use block\RuleTrait {
|
||||||
|
// Check Hr before checking lists
|
||||||
|
identifyHr as protected identifyAHr;
|
||||||
|
consumeHr as protected consumeAHr;
|
||||||
|
}
|
||||||
|
// include inline element parsing using traits
|
||||||
|
use inline\CodeTrait;
|
||||||
|
use inline\EmphStrongTrait;
|
||||||
|
use inline\LinkTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean whether to format markup according to HTML5 spec.
|
||||||
|
* Defaults to `false` which means that markup is formatted as HTML4.
|
||||||
|
*/
|
||||||
|
public $html5 = false;
|
||||||
|
|
||||||
|
protected function prepare()
|
||||||
|
{
|
||||||
|
// reset references
|
||||||
|
$this->references = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In general, just adding the trait with `use` is enough, however in some cases some fine tuning is desired
|
||||||
|
to get most expected parsing results. Elements are detected in alphabetical order of their identification
|
||||||
|
function. This means that if a line starting with `-` could be a list or a horizontal rule, the preference has to be set
|
||||||
|
by renaming the identification function. This is what is done with renaming `identifyHr` to `identifyAHr`
|
||||||
|
and `identifyBUl` to `identifyBUl`. The consume function always has to have the same name as the identification function
|
||||||
|
so this has to be renamed too.
|
||||||
|
|
||||||
|
There is also a conflict for parsing of the `<` character. This could either be a link/email enclosed in `<` and `>`
|
||||||
|
or an inline HTML tag. In order to resolve this conflict when adding the `LinkTrait`, we need to hide the `parseInlineHtml`
|
||||||
|
method of the `HtmlTrait`.
|
||||||
|
|
||||||
|
If you use any trait that uses the `$html5` property to adjust its output you also need to define this property.
|
||||||
|
|
||||||
|
If you use the link trait it may be useful to implement `prepare()` as shown above to reset references before
|
||||||
|
parsing to ensure you get a reusable object.
|
||||||
|
|
||||||
|
#### Define escapeable characters
|
||||||
|
|
||||||
|
Depending on the language features you have chosen there is a different set of characters that can be escaped
|
||||||
|
using `\`. The following is the set of escapeable characters for traditional markdown, you can copy it to your class
|
||||||
|
as is.
|
||||||
|
|
||||||
|
```php
|
||||||
|
/**
|
||||||
|
* @var array these are "escapeable" characters. When using one of these prefixed with a
|
||||||
|
* backslash, the character will be outputted without the backslash and is not interpreted
|
||||||
|
* as markdown.
|
||||||
|
*/
|
||||||
|
protected $escapeCharacters = [
|
||||||
|
'\\', // backslash
|
||||||
|
'`', // backtick
|
||||||
|
'*', // asterisk
|
||||||
|
'_', // underscore
|
||||||
|
'{', '}', // curly braces
|
||||||
|
'[', ']', // square brackets
|
||||||
|
'(', ')', // parentheses
|
||||||
|
'#', // hash mark
|
||||||
|
'+', // plus sign
|
||||||
|
'-', // minus sign (hyphen)
|
||||||
|
'.', // dot
|
||||||
|
'!', // exclamation mark
|
||||||
|
'<', '>',
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add custom rendering behavior
|
||||||
|
|
||||||
|
Optionally you may also want to adjust rendering behavior by overriding some methods.
|
||||||
|
You may refer to the `consumeParagraph()` method of the `Markdown` and `GithubMarkdown` classes for some inspiration
|
||||||
|
which define different rules for which elements are allowed to interrupt a paragraph.
|
||||||
|
|
||||||
|
|
||||||
|
Acknowledgements <a name="ack"></a>
|
||||||
|
----------------
|
||||||
|
|
||||||
|
I'd like to thank [@erusev][] for creating [Parsedown][] which heavily influenced this work and provided
|
||||||
|
the idea of the line based parsing approach.
|
||||||
|
|
||||||
|
[@erusev]: https://github.com/erusev "Emanuil Rusev"
|
||||||
|
[Parsedown]: http://parsedown.org/ "The Parsedown PHP Markdown parser"
|
||||||
|
|
||||||
|
FAQ <a name="faq"></a>
|
||||||
|
---
|
||||||
|
|
||||||
|
### Why another markdown parser?
|
||||||
|
|
||||||
|
While reviewing PHP markdown parsers for choosing one to use bundled with the [Yii framework 2.0][]
|
||||||
|
I found that most of the implementations use regex to replace patterns instead
|
||||||
|
of doing real parsing. This way extending them with new language elements is quite hard
|
||||||
|
as you have to come up with a complex regex, that matches your addition but does not mess
|
||||||
|
with other elements. Such additions are very common as you see on github which supports referencing
|
||||||
|
issues, users and commits in the comments.
|
||||||
|
A [real parser][] should use context aware methods that walk trough the text and
|
||||||
|
parse the tokens as they find them. The only implentation that I have found that uses
|
||||||
|
this approach is [Parsedown][] which also shows that this implementation is [much faster][benchmark]
|
||||||
|
than the regex way. Parsedown however is an implementation that focuses on speed and implements
|
||||||
|
its own flavor (mainly github flavored markdown) in one class and at the time of this writing was
|
||||||
|
not easily extensible.
|
||||||
|
|
||||||
|
Given the situation above I decided to start my own implementation using the parsing approach
|
||||||
|
from Parsedown and making it extensible creating a class for each markdown flavor that extend each
|
||||||
|
other in the way that also the markdown languages extend each other.
|
||||||
|
This allows you to choose between markdown language flavors and also provides a way to compose your
|
||||||
|
own flavor picking the best things from all.
|
||||||
|
I chose this approach as it is easier to implement and also more intuitive approach compared
|
||||||
|
to using callbacks to inject functionallity into the parser.
|
||||||
|
|
||||||
|
[real parser]: http://en.wikipedia.org/wiki/Parsing#Types_of_parser
|
||||||
|
|
||||||
|
[Parsedown]: http://parsedown.org/ "The Parsedown PHP Markdown parser"
|
||||||
|
|
||||||
|
[Yii framework 2.0]: https://github.com/yiisoft/yii2
|
||||||
|
|
||||||
|
### Where do I report bugs or rendering issues?
|
||||||
|
|
||||||
|
Just [open an issue][] on github, post your markdown code and describe the problem. You may also attach screenshots of the rendered HTML result to describe your problem.
|
||||||
|
|
||||||
|
[open an issue]: https://github.com/cebe/markdown/issues/new
|
||||||
|
|
||||||
|
### How can I contribute to this library?
|
||||||
|
|
||||||
|
Check the [CONTRIBUTING.md](CONTRIBUTING.md) file for more info.
|
||||||
|
|
||||||
|
|
||||||
|
### Am I free to use this?
|
||||||
|
|
||||||
|
This library is open source and licensed under the [MIT License][]. This means that you can do whatever you want
|
||||||
|
with it as long as you mention my name and include the [license file][license]. Check the [license][] for details.
|
||||||
|
|
||||||
|
[MIT License]: http://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
[license]: https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
|
||||||
|
Contact
|
||||||
|
-------
|
||||||
|
|
||||||
|
Feel free to contact me using [email](mailto:mail@cebe.cc) or [twitter](https://twitter.com/cebe_cc).
|
||||||
170
core/lib/composer/vendor/cebe/markdown/bin/markdown
vendored
Executable file
170
core/lib/composer/vendor/cebe/markdown/bin/markdown
vendored
Executable file
@@ -0,0 +1,170 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
$composerAutoload = [
|
||||||
|
__DIR__ . '/../vendor/autoload.php', // standalone with "composer install" run
|
||||||
|
__DIR__ . '/../../../autoload.php', // script is installed as a composer binary
|
||||||
|
];
|
||||||
|
foreach ($composerAutoload as $autoload) {
|
||||||
|
if (file_exists($autoload)) {
|
||||||
|
require($autoload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send all errors to stderr
|
||||||
|
ini_set('display_errors', 'stderr');
|
||||||
|
|
||||||
|
$flavor = 'cebe\\markdown\\Markdown';
|
||||||
|
$flavors = [
|
||||||
|
'gfm' => ['cebe\\markdown\\GithubMarkdown', __DIR__ . '/../GithubMarkdown.php'],
|
||||||
|
'extra' => ['cebe\\markdown\\MarkdownExtra', __DIR__ . '/../MarkdownExtra.php'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$full = false;
|
||||||
|
$src = [];
|
||||||
|
foreach($argv as $k => $arg) {
|
||||||
|
if ($k == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($arg[0] == '-') {
|
||||||
|
$arg = explode('=', $arg);
|
||||||
|
switch($arg[0]) {
|
||||||
|
case '--flavor':
|
||||||
|
if (isset($arg[1])) {
|
||||||
|
if (isset($flavors[$arg[1]])) {
|
||||||
|
require($flavors[$arg[1]][1]);
|
||||||
|
$flavor = $flavors[$arg[1]][0];
|
||||||
|
} else {
|
||||||
|
error("Unknown flavor: " . $arg[1], "usage");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error("Incomplete argument --flavor!", "usage");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '--full':
|
||||||
|
$full = true;
|
||||||
|
break;
|
||||||
|
case '-h':
|
||||||
|
case '--help':
|
||||||
|
echo "PHP Markdown to HTML converter\n";
|
||||||
|
echo "------------------------------\n\n";
|
||||||
|
echo "by Carsten Brandt <mail@cebe.cc>\n\n";
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unknown argument " . $arg[0], "usage");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$src[] = $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($src)) {
|
||||||
|
$markdown = file_get_contents("php://stdin");
|
||||||
|
} elseif (count($src) == 1) {
|
||||||
|
$file = reset($src);
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
error("File does not exist:" . $file);
|
||||||
|
}
|
||||||
|
$markdown = file_get_contents($file);
|
||||||
|
} else {
|
||||||
|
error("Converting multiple files is not yet supported.", "usage");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var cebe\markdown\Parser $md */
|
||||||
|
$md = new $flavor();
|
||||||
|
$markup = $md->parse($markdown);
|
||||||
|
|
||||||
|
if ($full) {
|
||||||
|
echo <<<HTML
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; }
|
||||||
|
code { background: #eeeeff; padding: 2px; }
|
||||||
|
li { margin-bottom: 5px; }
|
||||||
|
img { max-width: 1200px; }
|
||||||
|
table, td, th { border: solid 1px #ccc; border-collapse: collapse; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
$markup
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML;
|
||||||
|
} else {
|
||||||
|
echo $markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display usage information
|
||||||
|
*/
|
||||||
|
function usage() {
|
||||||
|
global $argv;
|
||||||
|
$cmd = $argv[0];
|
||||||
|
echo <<<EOF
|
||||||
|
Usage:
|
||||||
|
$cmd [--flavor=<flavor>] [--full] [file.md]
|
||||||
|
|
||||||
|
--flavor specifies the markdown flavor to use. If omitted the original markdown by John Gruber [1] will be used.
|
||||||
|
Available flavors:
|
||||||
|
|
||||||
|
gfm - Github flavored markdown [2]
|
||||||
|
extra - Markdown Extra [3]
|
||||||
|
|
||||||
|
--full ouput a full HTML page with head and body. If not given, only the parsed markdown will be output.
|
||||||
|
|
||||||
|
--help shows this usage information.
|
||||||
|
|
||||||
|
If no file is specified input will be read from STDIN.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Render a file with original markdown:
|
||||||
|
|
||||||
|
$cmd README.md > README.html
|
||||||
|
|
||||||
|
Render a file using gihtub flavored markdown:
|
||||||
|
|
||||||
|
$cmd --flavor=gfm README.md > README.html
|
||||||
|
|
||||||
|
Convert the original markdown description to html using STDIN:
|
||||||
|
|
||||||
|
curl http://daringfireball.net/projects/markdown/syntax.text | $cmd > md.html
|
||||||
|
|
||||||
|
|
||||||
|
[1] http://daringfireball.net/projects/markdown/syntax
|
||||||
|
[2] https://help.github.com/articles/github-flavored-markdown
|
||||||
|
[3] http://michelf.ca/projects/php-markdown/extra/
|
||||||
|
|
||||||
|
EOF;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send custom error message to stderr
|
||||||
|
* @param $message string
|
||||||
|
* @param $callback mixed called before script exit
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function error($message, $callback = null) {
|
||||||
|
$fe = fopen("php://stderr", "w");
|
||||||
|
fwrite($fe, "Error: " . $message . "\n");
|
||||||
|
|
||||||
|
if (is_callable($callback)) {
|
||||||
|
call_user_func($callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
66
core/lib/composer/vendor/cebe/markdown/block/CodeTrait.php
vendored
Normal file
66
core/lib/composer/vendor/cebe/markdown/block/CodeTrait.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the 4 space indented code blocks
|
||||||
|
*/
|
||||||
|
trait CodeTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of a code block.
|
||||||
|
*/
|
||||||
|
protected function identifyCode($line)
|
||||||
|
{
|
||||||
|
// indentation >= 4 or one tab is code
|
||||||
|
return ($l = $line[0]) === ' ' && $line[1] === ' ' && $line[2] === ' ' && $line[3] === ' ' || $l === "\t";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a code block element
|
||||||
|
*/
|
||||||
|
protected function consumeCode($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
|
||||||
|
$content = [];
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
|
||||||
|
// a line is considered to belong to this code block as long as it is intended by 4 spaces or a tab
|
||||||
|
if (isset($line[0]) && ($line[0] === "\t" || strncmp($line, ' ', 4) === 0)) {
|
||||||
|
$line = $line[0] === "\t" ? substr($line, 1) : substr($line, 4);
|
||||||
|
$content[] = $line;
|
||||||
|
// but also if it is empty and the next line is intended by 4 spaces or a tab
|
||||||
|
} elseif (($line === '' || rtrim($line) === '') && isset($lines[$i + 1][0]) &&
|
||||||
|
($lines[$i + 1][0] === "\t" || strncmp($lines[$i + 1], ' ', 4) === 0)) {
|
||||||
|
if ($line !== '') {
|
||||||
|
$line = $line[0] === "\t" ? substr($line, 1) : substr($line, 4);
|
||||||
|
}
|
||||||
|
$content[] = $line;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$block = [
|
||||||
|
'code',
|
||||||
|
'content' => implode("\n", $content),
|
||||||
|
];
|
||||||
|
return [$block, --$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a code block
|
||||||
|
*/
|
||||||
|
protected function renderCode($block)
|
||||||
|
{
|
||||||
|
$class = isset($block['language']) ? ' class="language-' . $block['language'] . '"' : '';
|
||||||
|
return "<pre><code$class>" . htmlspecialchars($block['content'] . "\n", ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8') . "</code></pre>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
58
core/lib/composer/vendor/cebe/markdown/block/FencedCodeTrait.php
vendored
Normal file
58
core/lib/composer/vendor/cebe/markdown/block/FencedCodeTrait.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the fenced code blocks
|
||||||
|
*
|
||||||
|
* automatically included 4 space indented code blocks
|
||||||
|
*/
|
||||||
|
trait FencedCodeTrait
|
||||||
|
{
|
||||||
|
use CodeTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of a fenced code block.
|
||||||
|
*/
|
||||||
|
protected function identifyFencedCode($line)
|
||||||
|
{
|
||||||
|
return ($line[0] === '`' && strncmp($line, '```', 3) === 0) ||
|
||||||
|
($line[0] === '~' && strncmp($line, '~~~', 3) === 0) ||
|
||||||
|
(isset($line[3]) && (
|
||||||
|
($line[3] === '`' && strncmp(ltrim($line), '```', 3) === 0) ||
|
||||||
|
($line[3] === '~' && strncmp(ltrim($line), '~~~', 3) === 0)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a fenced code block
|
||||||
|
*/
|
||||||
|
protected function consumeFencedCode($lines, $current)
|
||||||
|
{
|
||||||
|
$line = ltrim($lines[$current]);
|
||||||
|
$fence = substr($line, 0, $pos = strrpos($line, $line[0]) + 1);
|
||||||
|
$language = rtrim(substr($line, $pos));
|
||||||
|
// consume until end fence
|
||||||
|
$content = [];
|
||||||
|
for ($i = $current + 1, $count = count($lines); $i < $count; $i++) {
|
||||||
|
if (($pos = strpos($line = $lines[$i], $fence)) === false || $pos > 3) {
|
||||||
|
$content[] = $line;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$block = [
|
||||||
|
'code',
|
||||||
|
'content' => implode("\n", $content),
|
||||||
|
];
|
||||||
|
if (!empty($language)) {
|
||||||
|
$block['language'] = $language;
|
||||||
|
}
|
||||||
|
return [$block, $i];
|
||||||
|
}
|
||||||
|
}
|
||||||
70
core/lib/composer/vendor/cebe/markdown/block/HeadlineTrait.php
vendored
Normal file
70
core/lib/composer/vendor/cebe/markdown/block/HeadlineTrait.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the headline blocks
|
||||||
|
*/
|
||||||
|
trait HeadlineTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* identify a line as a headline
|
||||||
|
*/
|
||||||
|
protected function identifyHeadline($line, $lines, $current)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
// heading with #
|
||||||
|
$line[0] === '#' && !preg_match('/^#\d+/', $line)
|
||||||
|
||
|
||||||
|
// underlined headline
|
||||||
|
!empty($lines[$current + 1]) &&
|
||||||
|
(($l = $lines[$current + 1][0]) === '=' || $l === '-') &&
|
||||||
|
preg_match('/^(\-+|=+)\s*$/', $lines[$current + 1])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a headline
|
||||||
|
*/
|
||||||
|
protected function consumeHeadline($lines, $current)
|
||||||
|
{
|
||||||
|
if ($lines[$current][0] === '#') {
|
||||||
|
// ATX headline
|
||||||
|
$level = 1;
|
||||||
|
while (isset($lines[$current][$level]) && $lines[$current][$level] === '#' && $level < 6) {
|
||||||
|
$level++;
|
||||||
|
}
|
||||||
|
$block = [
|
||||||
|
'headline',
|
||||||
|
'content' => $this->parseInline(trim($lines[$current], "# \t")),
|
||||||
|
'level' => $level,
|
||||||
|
];
|
||||||
|
return [$block, $current];
|
||||||
|
} else {
|
||||||
|
// underlined headline
|
||||||
|
$block = [
|
||||||
|
'headline',
|
||||||
|
'content' => $this->parseInline($lines[$current]),
|
||||||
|
'level' => $lines[$current + 1][0] === '=' ? 1 : 2,
|
||||||
|
];
|
||||||
|
return [$block, $current + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a headline
|
||||||
|
*/
|
||||||
|
protected function renderHeadline($block)
|
||||||
|
{
|
||||||
|
$tag = 'h' . $block['level'];
|
||||||
|
return "<$tag>" . $this->renderAbsy($block['content']) . "</$tag>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseInline($text);
|
||||||
|
abstract protected function renderAbsy($absy);
|
||||||
|
}
|
||||||
168
core/lib/composer/vendor/cebe/markdown/block/HtmlTrait.php
vendored
Normal file
168
core/lib/composer/vendor/cebe/markdown/block/HtmlTrait.php
vendored
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds inline and block HTML support
|
||||||
|
*/
|
||||||
|
trait HtmlTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array HTML elements considered as inline elements.
|
||||||
|
* @see http://www.w3.org/wiki/HTML/Elements#Text-level_semantics
|
||||||
|
*/
|
||||||
|
protected $inlineHtmlElements = [
|
||||||
|
'a', 'abbr', 'acronym',
|
||||||
|
'b', 'basefont', 'bdo', 'big', 'br', 'button', 'blink',
|
||||||
|
'cite', 'code',
|
||||||
|
'del', 'dfn',
|
||||||
|
'em',
|
||||||
|
'font',
|
||||||
|
'i', 'img', 'ins', 'input', 'iframe',
|
||||||
|
'kbd',
|
||||||
|
'label', 'listing',
|
||||||
|
'map', 'mark',
|
||||||
|
'nobr',
|
||||||
|
'object',
|
||||||
|
'q',
|
||||||
|
'rp', 'rt', 'ruby',
|
||||||
|
's', 'samp', 'script', 'select', 'small', 'spacer', 'span', 'strong', 'sub', 'sup',
|
||||||
|
'tt', 'var',
|
||||||
|
'u',
|
||||||
|
'wbr',
|
||||||
|
'time',
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* @var array HTML elements known to be self-closing.
|
||||||
|
*/
|
||||||
|
protected $selfClosingHtmlElements = [
|
||||||
|
'br', 'hr', 'img', 'input', 'nobr',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of a HTML block.
|
||||||
|
*/
|
||||||
|
protected function identifyHtml($line, $lines, $current)
|
||||||
|
{
|
||||||
|
if ($line[0] !== '<' || isset($line[1]) && $line[1] == ' ') {
|
||||||
|
return false; // no html tag
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp($line, '<!--', 4) === 0) {
|
||||||
|
return true; // a html comment
|
||||||
|
}
|
||||||
|
|
||||||
|
$gtPos = strpos($lines[$current], '>');
|
||||||
|
$spacePos = strpos($lines[$current], ' ');
|
||||||
|
if ($gtPos === false && $spacePos === false) {
|
||||||
|
return false; // no html tag
|
||||||
|
} elseif ($spacePos === false) {
|
||||||
|
$tag = rtrim(substr($line, 1, $gtPos - 1), '/');
|
||||||
|
} else {
|
||||||
|
$tag = rtrim(substr($line, 1, min($gtPos, $spacePos) - 1), '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ctype_alnum($tag) || in_array(strtolower($tag), $this->inlineHtmlElements)) {
|
||||||
|
return false; // no html tag or inline html tag
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for an HTML block
|
||||||
|
*/
|
||||||
|
protected function consumeHtml($lines, $current)
|
||||||
|
{
|
||||||
|
$content = [];
|
||||||
|
if (strncmp($lines[$current], '<!--', 4) === 0) { // html comment
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
$content[] = $line;
|
||||||
|
if (strpos($line, '-->') !== false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$tag = rtrim(substr($lines[$current], 1, min(strpos($lines[$current], '>'), strpos($lines[$current] . ' ', ' ')) - 1), '/');
|
||||||
|
$level = 0;
|
||||||
|
if (in_array($tag, $this->selfClosingHtmlElements)) {
|
||||||
|
$level--;
|
||||||
|
}
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
$content[] = $line;
|
||||||
|
$level += substr_count($line, "<$tag") - substr_count($line, "</$tag>") - substr_count($line, "/>");
|
||||||
|
if ($level <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$block = [
|
||||||
|
'html',
|
||||||
|
'content' => implode("\n", $content),
|
||||||
|
];
|
||||||
|
return [$block, $i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders an HTML block
|
||||||
|
*/
|
||||||
|
protected function renderHtml($block)
|
||||||
|
{
|
||||||
|
return $block['content'] . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an & or a html entity definition.
|
||||||
|
* @marker &
|
||||||
|
*/
|
||||||
|
protected function parseEntity($text)
|
||||||
|
{
|
||||||
|
// html entities e.g. © © ©
|
||||||
|
if (preg_match('/^&#?[\w\d]+;/', $text, $matches)) {
|
||||||
|
return [['inlineHtml', $matches[0]], strlen($matches[0])];
|
||||||
|
} else {
|
||||||
|
return [['text', '&'], 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* renders a html entity.
|
||||||
|
*/
|
||||||
|
protected function renderInlineHtml($block)
|
||||||
|
{
|
||||||
|
return $block[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses inline HTML.
|
||||||
|
* @marker <
|
||||||
|
*/
|
||||||
|
protected function parseInlineHtml($text)
|
||||||
|
{
|
||||||
|
if (strpos($text, '>') !== false) {
|
||||||
|
if (preg_match('~^</?(\w+\d?)( .*?)?>~s', $text, $matches)) {
|
||||||
|
// HTML tags
|
||||||
|
return [['inlineHtml', $matches[0]], strlen($matches[0])];
|
||||||
|
} elseif (preg_match('~^<!--.*?-->~s', $text, $matches)) {
|
||||||
|
// HTML comments
|
||||||
|
return [['inlineHtml', $matches[0]], strlen($matches[0])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [['text', '<'], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes `>` characters.
|
||||||
|
* @marker >
|
||||||
|
*/
|
||||||
|
protected function parseGt($text)
|
||||||
|
{
|
||||||
|
return [['text', '>'], 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
202
core/lib/composer/vendor/cebe/markdown/block/ListTrait.php
vendored
Normal file
202
core/lib/composer/vendor/cebe/markdown/block/ListTrait.php
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the list blocks
|
||||||
|
*/
|
||||||
|
trait ListTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool enable support `start` attribute of ordered lists. This means that lists
|
||||||
|
* will start with the number you actually type in markdown and not the HTML generated one.
|
||||||
|
* Defaults to `false` which means that numeration of all ordered lists(<ol>) starts with 1.
|
||||||
|
*/
|
||||||
|
public $keepListStartNumber = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of an ordered list.
|
||||||
|
*/
|
||||||
|
protected function identifyOl($line)
|
||||||
|
{
|
||||||
|
return (($l = $line[0]) > '0' && $l <= '9' || $l === ' ') && preg_match('/^ {0,3}\d+\.[ \t]/', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of an unordered list.
|
||||||
|
*/
|
||||||
|
protected function identifyUl($line)
|
||||||
|
{
|
||||||
|
$l = $line[0];
|
||||||
|
return ($l === '-' || $l === '+' || $l === '*') && (isset($line[1]) && (($l1 = $line[1]) === ' ' || $l1 === "\t")) ||
|
||||||
|
($l === ' ' && preg_match('/^ {0,3}[\-\+\*][ \t]/', $line));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for an ordered list
|
||||||
|
*/
|
||||||
|
protected function consumeOl($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
|
||||||
|
$block = [
|
||||||
|
'list',
|
||||||
|
'list' => 'ol',
|
||||||
|
'attr' => [],
|
||||||
|
'items' => [],
|
||||||
|
];
|
||||||
|
return $this->consumeList($lines, $current, $block, 'ol');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for an unordered list
|
||||||
|
*/
|
||||||
|
protected function consumeUl($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
|
||||||
|
$block = [
|
||||||
|
'list',
|
||||||
|
'list' => 'ul',
|
||||||
|
'items' => [],
|
||||||
|
];
|
||||||
|
return $this->consumeList($lines, $current, $block, 'ul');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function consumeList($lines, $current, $block, $type)
|
||||||
|
{
|
||||||
|
$item = 0;
|
||||||
|
$indent = '';
|
||||||
|
$len = 0;
|
||||||
|
$lastLineEmpty = false;
|
||||||
|
// track the indentation of list markers, if indented more than previous element
|
||||||
|
// a list marker is considered to be long to a lower level
|
||||||
|
$leadSpace = 3;
|
||||||
|
$marker = $type === 'ul' ? ltrim($lines[$current])[0] : '';
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
// match list marker on the beginning of the line
|
||||||
|
$pattern = ($type === 'ol') ? '/^( {0,'.$leadSpace.'})(\d+)\.[ \t]+/' : '/^( {0,'.$leadSpace.'})\\'.$marker.'[ \t]+/';
|
||||||
|
if (preg_match($pattern, $line, $matches)) {
|
||||||
|
if (($len = substr_count($matches[0], "\t")) > 0) {
|
||||||
|
$indent = str_repeat("\t", $len);
|
||||||
|
$line = substr($line, strlen($matches[0]));
|
||||||
|
} else {
|
||||||
|
$len = strlen($matches[0]);
|
||||||
|
$indent = str_repeat(' ', $len);
|
||||||
|
$line = substr($line, $len);
|
||||||
|
}
|
||||||
|
if ($i === $current) {
|
||||||
|
$leadSpace = strlen($matches[1]) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'ol' && $this->keepListStartNumber) {
|
||||||
|
// attr `start` for ol
|
||||||
|
if (!isset($block['attr']['start']) && isset($matches[2])) {
|
||||||
|
$block['attr']['start'] = $matches[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$block['items'][++$item][] = $line;
|
||||||
|
$block['lazyItems'][$item] = $lastLineEmpty;
|
||||||
|
$lastLineEmpty = false;
|
||||||
|
} elseif (ltrim($line) === '') {
|
||||||
|
// line is empty, may be a lazy list
|
||||||
|
$lastLineEmpty = true;
|
||||||
|
|
||||||
|
// two empty lines will end the list
|
||||||
|
if (!isset($lines[$i + 1][0])) {
|
||||||
|
break;
|
||||||
|
|
||||||
|
// next item is the continuation of this list -> lazy list
|
||||||
|
} elseif (preg_match($pattern, $lines[$i + 1])) {
|
||||||
|
$block['items'][$item][] = $line;
|
||||||
|
$block['lazyItems'][$item] = true;
|
||||||
|
|
||||||
|
// next item is indented as much as this list -> lazy list if it is not a reference
|
||||||
|
} elseif (strncmp($lines[$i + 1], $indent, $len) === 0 || !empty($lines[$i + 1]) && $lines[$i + 1][0] == "\t") {
|
||||||
|
$block['items'][$item][] = $line;
|
||||||
|
$nextLine = $lines[$i + 1][0] === "\t" ? substr($lines[$i + 1], 1) : substr($lines[$i + 1], $len);
|
||||||
|
$block['lazyItems'][$item] = empty($nextLine) || !method_exists($this, 'identifyReference') || !$this->identifyReference($nextLine);
|
||||||
|
|
||||||
|
// everything else ends the list
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($line[0] === "\t") {
|
||||||
|
$line = substr($line, 1);
|
||||||
|
} elseif (strncmp($line, $indent, $len) === 0) {
|
||||||
|
$line = substr($line, $len);
|
||||||
|
}
|
||||||
|
$block['items'][$item][] = $line;
|
||||||
|
$lastLineEmpty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if next line is <hr>, end the list
|
||||||
|
if (!empty($lines[$i + 1]) && method_exists($this, 'identifyHr') && $this->identifyHr($lines[$i + 1])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($block['items'] as $itemId => $itemLines) {
|
||||||
|
$content = [];
|
||||||
|
if (!$block['lazyItems'][$itemId]) {
|
||||||
|
$firstPar = [];
|
||||||
|
while (!empty($itemLines) && rtrim($itemLines[0]) !== '' && $this->detectLineType($itemLines, 0) === 'paragraph') {
|
||||||
|
$firstPar[] = array_shift($itemLines);
|
||||||
|
}
|
||||||
|
$content = $this->parseInline(implode("\n", $firstPar));
|
||||||
|
}
|
||||||
|
if (!empty($itemLines)) {
|
||||||
|
$content = array_merge($content, $this->parseBlocks($itemLines));
|
||||||
|
}
|
||||||
|
$block['items'][$itemId] = $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$block, $i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a list
|
||||||
|
*/
|
||||||
|
protected function renderList($block)
|
||||||
|
{
|
||||||
|
$type = $block['list'];
|
||||||
|
|
||||||
|
if (!empty($block['attr'])) {
|
||||||
|
$output = "<$type " . $this->generateHtmlAttributes($block['attr']) . ">\n";
|
||||||
|
} else {
|
||||||
|
$output = "<$type>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($block['items'] as $item => $itemLines) {
|
||||||
|
$output .= '<li>' . $this->renderAbsy($itemLines). "</li>\n";
|
||||||
|
}
|
||||||
|
return $output . "</$type>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return html attributes string from [attrName => attrValue] list
|
||||||
|
* @param array $attributes the attribute name-value pairs.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function generateHtmlAttributes($attributes)
|
||||||
|
{
|
||||||
|
foreach ($attributes as $name => $value) {
|
||||||
|
$attributes[$name] = "$name=\"$value\"";
|
||||||
|
}
|
||||||
|
return implode(' ', $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseBlocks($lines);
|
||||||
|
abstract protected function parseInline($text);
|
||||||
|
abstract protected function renderAbsy($absy);
|
||||||
|
abstract protected function detectLineType($lines, $current);
|
||||||
|
}
|
||||||
63
core/lib/composer/vendor/cebe/markdown/block/QuoteTrait.php
vendored
Normal file
63
core/lib/composer/vendor/cebe/markdown/block/QuoteTrait.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the block quote elements
|
||||||
|
*/
|
||||||
|
trait QuoteTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of a block quote.
|
||||||
|
*/
|
||||||
|
protected function identifyQuote($line)
|
||||||
|
{
|
||||||
|
return $line[0] === '>' && (!isset($line[1]) || ($l1 = $line[1]) === ' ' || $l1 === "\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a blockquote element
|
||||||
|
*/
|
||||||
|
protected function consumeQuote($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
$content = [];
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = $lines[$i];
|
||||||
|
if (ltrim($line) !== '') {
|
||||||
|
if ($line[0] == '>' && !isset($line[1])) {
|
||||||
|
$line = '';
|
||||||
|
} elseif (strncmp($line, '> ', 2) === 0) {
|
||||||
|
$line = substr($line, 2);
|
||||||
|
}
|
||||||
|
$content[] = $line;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$block = [
|
||||||
|
'quote',
|
||||||
|
'content' => $this->parseBlocks($content),
|
||||||
|
'simple' => true,
|
||||||
|
];
|
||||||
|
return [$block, $i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a blockquote
|
||||||
|
*/
|
||||||
|
protected function renderQuote($block)
|
||||||
|
{
|
||||||
|
return '<blockquote>' . $this->renderAbsy($block['content']) . "</blockquote>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseBlocks($lines);
|
||||||
|
abstract protected function renderAbsy($absy);
|
||||||
|
}
|
||||||
40
core/lib/composer/vendor/cebe/markdown/block/RuleTrait.php
vendored
Normal file
40
core/lib/composer/vendor/cebe/markdown/block/RuleTrait.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds horizontal rules
|
||||||
|
*/
|
||||||
|
trait RuleTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* identify a line as a horizontal rule.
|
||||||
|
*/
|
||||||
|
protected function identifyHr($line)
|
||||||
|
{
|
||||||
|
// at least 3 of -, * or _ on one line make a hr
|
||||||
|
return (($l = $line[0]) === ' ' || $l === '-' || $l === '*' || $l === '_') && preg_match('/^ {0,3}([\-\*_])\s*\1\s*\1(\1|\s)*$/', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume a horizontal rule
|
||||||
|
*/
|
||||||
|
protected function consumeHr($lines, $current)
|
||||||
|
{
|
||||||
|
return [['hr'], $current];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a horizontal rule
|
||||||
|
*/
|
||||||
|
protected function renderHr($block)
|
||||||
|
{
|
||||||
|
return $this->html5 ? "<hr>\n" : "<hr />\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
156
core/lib/composer/vendor/cebe/markdown/block/TableTrait.php
vendored
Normal file
156
core/lib/composer/vendor/cebe/markdown/block/TableTrait.php
vendored
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the table blocks
|
||||||
|
*/
|
||||||
|
trait TableTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* identify a line as the beginning of a table block.
|
||||||
|
*/
|
||||||
|
protected function identifyTable($line, $lines, $current)
|
||||||
|
{
|
||||||
|
return strpos($line, '|') !== false && isset($lines[$current + 1])
|
||||||
|
&& preg_match('~^\\s*\\|?(\\s*:?-[\\-\\s]*:?\\s*\\|?)*\\s*$~', $lines[$current + 1])
|
||||||
|
&& strpos($lines[$current + 1], '|') !== false
|
||||||
|
&& isset($lines[$current + 2]) && trim($lines[$current + 1]) !== '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume lines for a table
|
||||||
|
*/
|
||||||
|
protected function consumeTable($lines, $current)
|
||||||
|
{
|
||||||
|
// consume until newline
|
||||||
|
|
||||||
|
$block = [
|
||||||
|
'table',
|
||||||
|
'cols' => [],
|
||||||
|
'rows' => [],
|
||||||
|
];
|
||||||
|
for ($i = $current, $count = count($lines); $i < $count; $i++) {
|
||||||
|
$line = trim($lines[$i]);
|
||||||
|
|
||||||
|
// extract alignment from second line
|
||||||
|
if ($i == $current+1) {
|
||||||
|
$cols = explode('|', trim($line, ' |'));
|
||||||
|
foreach($cols as $col) {
|
||||||
|
$col = trim($col);
|
||||||
|
if (empty($col)) {
|
||||||
|
$block['cols'][] = '';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$l = ($col[0] === ':');
|
||||||
|
$r = (substr($col, -1, 1) === ':');
|
||||||
|
if ($l && $r) {
|
||||||
|
$block['cols'][] = 'center';
|
||||||
|
} elseif ($l) {
|
||||||
|
$block['cols'][] = 'left';
|
||||||
|
} elseif ($r) {
|
||||||
|
$block['cols'][] = 'right';
|
||||||
|
} else {
|
||||||
|
$block['cols'][] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($line === '' || substr($lines[$i], 0, 4) === ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($line[0] === '|') {
|
||||||
|
$line = substr($line, 1);
|
||||||
|
}
|
||||||
|
if (substr($line, -1, 1) === '|' && (substr($line, -2, 2) !== '\\|' || substr($line, -3, 3) === '\\\\|')) {
|
||||||
|
$line = substr($line, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_unshift($this->context, 'table');
|
||||||
|
$row = $this->parseInline($line);
|
||||||
|
array_shift($this->context);
|
||||||
|
|
||||||
|
$r = count($block['rows']);
|
||||||
|
$c = 0;
|
||||||
|
$block['rows'][] = [];
|
||||||
|
foreach ($row as $absy) {
|
||||||
|
if (!isset($block['rows'][$r][$c])) {
|
||||||
|
$block['rows'][$r][] = [];
|
||||||
|
}
|
||||||
|
if ($absy[0] === 'tableBoundary') {
|
||||||
|
$c++;
|
||||||
|
} else {
|
||||||
|
$block['rows'][$r][$c][] = $absy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$block, --$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* render a table block
|
||||||
|
*/
|
||||||
|
protected function renderTable($block)
|
||||||
|
{
|
||||||
|
$head = '';
|
||||||
|
$body = '';
|
||||||
|
$cols = $block['cols'];
|
||||||
|
$first = true;
|
||||||
|
foreach($block['rows'] as $row) {
|
||||||
|
$cellTag = $first ? 'th' : 'td';
|
||||||
|
$tds = '';
|
||||||
|
foreach ($row as $c => $cell) {
|
||||||
|
$align = empty($cols[$c]) ? '' : ' align="' . $cols[$c] . '"';
|
||||||
|
$tds .= "<$cellTag$align>" . trim($this->renderAbsy($cell)) . "</$cellTag>";
|
||||||
|
}
|
||||||
|
if ($first) {
|
||||||
|
$head .= "<tr>$tds</tr>\n";
|
||||||
|
} else {
|
||||||
|
$body .= "<tr>$tds</tr>\n";
|
||||||
|
}
|
||||||
|
$first = false;
|
||||||
|
}
|
||||||
|
return $this->composeTable($head, $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method composes a table from parsed body and head HTML.
|
||||||
|
*
|
||||||
|
* You may override this method to customize the table rendering, for example by
|
||||||
|
* adding a `class` to the table tag:
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* return "<table class="table table-striped">\n<thead>\n$head</thead>\n<tbody>\n$body</tbody>\n</table>\n"
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $head table head HTML.
|
||||||
|
* @param string $body table body HTML.
|
||||||
|
* @return string the complete table HTML.
|
||||||
|
* @since 1.2.0
|
||||||
|
*/
|
||||||
|
protected function composeTable($head, $body)
|
||||||
|
{
|
||||||
|
return "<table>\n<thead>\n$head</thead>\n<tbody>\n$body</tbody>\n</table>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @marker |
|
||||||
|
*/
|
||||||
|
protected function parseTd($markdown)
|
||||||
|
{
|
||||||
|
if (isset($this->context[1]) && $this->context[1] === 'table') {
|
||||||
|
return [['tableBoundary'], isset($markdown[1]) && $markdown[1] === ' ' ? 2 : 1];
|
||||||
|
}
|
||||||
|
return [['text', $markdown[0]], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseInline($text);
|
||||||
|
abstract protected function renderAbsy($absy);
|
||||||
|
}
|
||||||
42
core/lib/composer/vendor/cebe/markdown/composer.json
vendored
Normal file
42
core/lib/composer/vendor/cebe/markdown/composer.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "cebe/markdown",
|
||||||
|
"description": "A super fast, highly extensible markdown parser for PHP",
|
||||||
|
"keywords": ["markdown", "gfm", "markdown-extra", "fast", "extensible"],
|
||||||
|
"homepage": "https://github.com/cebe/markdown#readme",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Carsten Brandt",
|
||||||
|
"email": "mail@cebe.cc",
|
||||||
|
"homepage": "http://cebe.cc/",
|
||||||
|
"role": "Creator"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/cebe/markdown/issues",
|
||||||
|
"source": "https://github.com/cebe/markdown"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4.0",
|
||||||
|
"lib-pcre": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "4.1.*",
|
||||||
|
"facebook/xhprof": "*@dev",
|
||||||
|
"cebe/indent": "*"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"cebe\\markdown\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/markdown"
|
||||||
|
],
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.2.x-dev"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
core/lib/composer/vendor/cebe/markdown/inline/CodeTrait.php
vendored
Normal file
45
core/lib/composer/vendor/cebe/markdown/inline/CodeTrait.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\inline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds inline code elements
|
||||||
|
*/
|
||||||
|
trait CodeTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parses an inline code span `` ` ``.
|
||||||
|
* @marker `
|
||||||
|
*/
|
||||||
|
protected function parseInlineCode($text)
|
||||||
|
{
|
||||||
|
if (preg_match('/^(``+)\s(.+?)\s\1/s', $text, $matches)) { // code with enclosed backtick
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'inlineCode',
|
||||||
|
$matches[2],
|
||||||
|
],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
} elseif (preg_match('/^`(.+?)`/s', $text, $matches)) {
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'inlineCode',
|
||||||
|
$matches[1],
|
||||||
|
],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [['text', $text[0]], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderInlineCode($block)
|
||||||
|
{
|
||||||
|
return '<code>' . htmlspecialchars($block[1], ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8') . '</code>';
|
||||||
|
}
|
||||||
|
}
|
||||||
87
core/lib/composer/vendor/cebe/markdown/inline/EmphStrongTrait.php
vendored
Normal file
87
core/lib/composer/vendor/cebe/markdown/inline/EmphStrongTrait.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\inline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds inline emphasizes and strong elements
|
||||||
|
*/
|
||||||
|
trait EmphStrongTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parses emphasized and strong elements.
|
||||||
|
* @marker _
|
||||||
|
* @marker *
|
||||||
|
*/
|
||||||
|
protected function parseEmphStrong($text)
|
||||||
|
{
|
||||||
|
$marker = $text[0];
|
||||||
|
|
||||||
|
if (!isset($text[1])) {
|
||||||
|
return [['text', $text[0]], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($marker == $text[1]) { // strong
|
||||||
|
// work around a PHP bug that crashes with a segfault on too much regex backtrack
|
||||||
|
// check whether the end marker exists in the text
|
||||||
|
// https://github.com/erusev/parsedown/issues/443
|
||||||
|
// https://bugs.php.net/bug.php?id=45735
|
||||||
|
if (strpos($text, $marker . $marker, 2) === false) {
|
||||||
|
return [['text', $text[0] . $text[1]], 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($marker === '*' && preg_match('/^[*]{2}((?>\\\\[*]|[^*]|[*][^*]*[*])+?)[*]{2}/s', $text, $matches) ||
|
||||||
|
$marker === '_' && preg_match('/^__((?>\\\\_|[^_]|_[^_]*_)+?)__/us', $text, $matches)) {
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'strong',
|
||||||
|
$this->parseInline($matches[1]),
|
||||||
|
],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else { // emph
|
||||||
|
// work around a PHP bug that crashes with a segfault on too much regex backtrack
|
||||||
|
// check whether the end marker exists in the text
|
||||||
|
// https://github.com/erusev/parsedown/issues/443
|
||||||
|
// https://bugs.php.net/bug.php?id=45735
|
||||||
|
if (strpos($text, $marker, 1) === false) {
|
||||||
|
return [['text', $text[0]], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($marker === '*' && preg_match('/^[*]((?>\\\\[*]|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*][^*])/s', $text, $matches) ||
|
||||||
|
$marker === '_' && preg_match('/^_((?>\\\\_|[^_]|__[^_]*__)+?)_(?!_[^_])\b/us', $text, $matches)) {
|
||||||
|
// if only a single whitespace or nothing is contained in an emphasis, do not consider it valid
|
||||||
|
if ($matches[1] === '' || $matches[1] === ' ') {
|
||||||
|
return [['text', $text[0]], 1];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'emph',
|
||||||
|
$this->parseInline($matches[1]),
|
||||||
|
],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [['text', $text[0]], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderStrong($block)
|
||||||
|
{
|
||||||
|
return '<strong>' . $this->renderAbsy($block[1]) . '</strong>';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderEmph($block)
|
||||||
|
{
|
||||||
|
return '<em>' . $this->renderAbsy($block[1]) . '</em>';
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseInline($text);
|
||||||
|
abstract protected function renderAbsy($blocks);
|
||||||
|
}
|
||||||
287
core/lib/composer/vendor/cebe/markdown/inline/LinkTrait.php
vendored
Normal file
287
core/lib/composer/vendor/cebe/markdown/inline/LinkTrait.php
vendored
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\inline;
|
||||||
|
|
||||||
|
// work around https://github.com/facebook/hhvm/issues/1120
|
||||||
|
defined('ENT_HTML401') || define('ENT_HTML401', 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addes links and images as well as url markers.
|
||||||
|
*
|
||||||
|
* This trait conflicts with the HtmlTrait. If both are used together,
|
||||||
|
* you have to define a resolution, by defining the HtmlTrait::parseInlineHtml
|
||||||
|
* as private so it is not used directly:
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* use block\HtmlTrait {
|
||||||
|
* parseInlineHtml as private parseInlineHtml;
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If the method exists it is called internally by this trait.
|
||||||
|
*
|
||||||
|
* Also make sure to reset references on prepare():
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* protected function prepare()
|
||||||
|
* {
|
||||||
|
* // reset references
|
||||||
|
* $this->references = [];
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
trait LinkTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array a list of defined references in this document.
|
||||||
|
*/
|
||||||
|
protected $references = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove backslash from escaped characters
|
||||||
|
* @param $text
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function replaceEscape($text)
|
||||||
|
{
|
||||||
|
$strtr = [];
|
||||||
|
foreach($this->escapeCharacters as $char) {
|
||||||
|
$strtr["\\$char"] = $char;
|
||||||
|
}
|
||||||
|
return strtr($text, $strtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a link indicated by `[`.
|
||||||
|
* @marker [
|
||||||
|
*/
|
||||||
|
protected function parseLink($markdown)
|
||||||
|
{
|
||||||
|
if (!in_array('parseLink', array_slice($this->context, 1)) && ($parts = $this->parseLinkOrImage($markdown)) !== false) {
|
||||||
|
list($text, $url, $title, $offset, $key) = $parts;
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'link',
|
||||||
|
'text' => $this->parseInline($text),
|
||||||
|
'url' => $url,
|
||||||
|
'title' => $title,
|
||||||
|
'refkey' => $key,
|
||||||
|
'orig' => substr($markdown, 0, $offset),
|
||||||
|
],
|
||||||
|
$offset
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// remove all starting [ markers to avoid next one to be parsed as link
|
||||||
|
$result = '[';
|
||||||
|
$i = 1;
|
||||||
|
while (isset($markdown[$i]) && $markdown[$i] === '[') {
|
||||||
|
$result .= '[';
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
return [['text', $result], $i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an image indicated by `![`.
|
||||||
|
* @marker ![
|
||||||
|
*/
|
||||||
|
protected function parseImage($markdown)
|
||||||
|
{
|
||||||
|
if (($parts = $this->parseLinkOrImage(substr($markdown, 1))) !== false) {
|
||||||
|
list($text, $url, $title, $offset, $key) = $parts;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'image',
|
||||||
|
'text' => $text,
|
||||||
|
'url' => $url,
|
||||||
|
'title' => $title,
|
||||||
|
'refkey' => $key,
|
||||||
|
'orig' => substr($markdown, 0, $offset + 1),
|
||||||
|
],
|
||||||
|
$offset + 1
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// remove all starting [ markers to avoid next one to be parsed as link
|
||||||
|
$result = '!';
|
||||||
|
$i = 1;
|
||||||
|
while (isset($markdown[$i]) && $markdown[$i] === '[') {
|
||||||
|
$result .= '[';
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
return [['text', $result], $i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseLinkOrImage($markdown)
|
||||||
|
{
|
||||||
|
if (strpos($markdown, ']') !== false && preg_match('/\[((?>[^\]\[]+|(?R))*)\]/', $markdown, $textMatches)) { // TODO improve bracket regex
|
||||||
|
$text = $textMatches[1];
|
||||||
|
$offset = strlen($textMatches[0]);
|
||||||
|
$markdown = substr($markdown, $offset);
|
||||||
|
|
||||||
|
$pattern = <<<REGEXP
|
||||||
|
/(?(R) # in case of recursion match parentheses
|
||||||
|
\(((?>[^\s()]+)|(?R))*\)
|
||||||
|
| # else match a link with title
|
||||||
|
^\(\s*(((?>[^\s()]+)|(?R))*)(\s+"(.*?)")?\s*\)
|
||||||
|
)/x
|
||||||
|
REGEXP;
|
||||||
|
if (preg_match($pattern, $markdown, $refMatches)) {
|
||||||
|
// inline link
|
||||||
|
return [
|
||||||
|
$text,
|
||||||
|
isset($refMatches[2]) ? $this->replaceEscape($refMatches[2]) : '', // url
|
||||||
|
empty($refMatches[5]) ? null: $refMatches[5], // title
|
||||||
|
$offset + strlen($refMatches[0]), // offset
|
||||||
|
null, // reference key
|
||||||
|
];
|
||||||
|
} elseif (preg_match('/^([ \n]?\[(.*?)\])?/s', $markdown, $refMatches)) {
|
||||||
|
// reference style link
|
||||||
|
if (empty($refMatches[2])) {
|
||||||
|
$key = strtolower($text);
|
||||||
|
} else {
|
||||||
|
$key = strtolower($refMatches[2]);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
$text,
|
||||||
|
null, // url
|
||||||
|
null, // title
|
||||||
|
$offset + strlen($refMatches[0]), // offset
|
||||||
|
$key,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses inline HTML.
|
||||||
|
* @marker <
|
||||||
|
*/
|
||||||
|
protected function parseLt($text)
|
||||||
|
{
|
||||||
|
if (strpos($text, '>') !== false) {
|
||||||
|
if (!in_array('parseLink', $this->context)) { // do not allow links in links
|
||||||
|
if (preg_match('/^<([^\s>]*?@[^\s]*?\.\w+?)>/', $text, $matches)) {
|
||||||
|
// email address
|
||||||
|
return [
|
||||||
|
['email', $this->replaceEscape($matches[1])],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
} elseif (preg_match('/^<([a-z]{3,}:\/\/[^\s]+?)>/', $text, $matches)) {
|
||||||
|
// URL
|
||||||
|
return [
|
||||||
|
['url', $this->replaceEscape($matches[1])],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// try inline HTML if it was neither a URL nor email if HtmlTrait is included.
|
||||||
|
if (method_exists($this, 'parseInlineHtml')) {
|
||||||
|
return $this->parseInlineHtml($text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [['text', '<'], 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderEmail($block)
|
||||||
|
{
|
||||||
|
$email = htmlspecialchars($block[1], ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||||
|
return "<a href=\"mailto:$email\">$email</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderUrl($block)
|
||||||
|
{
|
||||||
|
$url = htmlspecialchars($block[1], ENT_COMPAT | ENT_HTML401, 'UTF-8');
|
||||||
|
$decodedUrl = urldecode($block[1]);
|
||||||
|
$secureUrlText = preg_match('//u', $decodedUrl) ? $decodedUrl : $block[1];
|
||||||
|
$text = htmlspecialchars($secureUrlText, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||||
|
return "<a href=\"$url\">$text</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function lookupReference($key)
|
||||||
|
{
|
||||||
|
$normalizedKey = preg_replace('/\s+/', ' ', $key);
|
||||||
|
if (isset($this->references[$key]) || isset($this->references[$key = $normalizedKey])) {
|
||||||
|
return $this->references[$key];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderLink($block)
|
||||||
|
{
|
||||||
|
if (isset($block['refkey'])) {
|
||||||
|
if (($ref = $this->lookupReference($block['refkey'])) !== false) {
|
||||||
|
$block = array_merge($block, $ref);
|
||||||
|
} else {
|
||||||
|
if (strncmp($block['orig'], '[', 1) === 0) {
|
||||||
|
return '[' . $this->renderAbsy($this->parseInline(substr($block['orig'], 1)));
|
||||||
|
}
|
||||||
|
return $block['orig'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '<a href="' . htmlspecialchars($block['url'], ENT_COMPAT | ENT_HTML401, 'UTF-8') . '"'
|
||||||
|
. (empty($block['title']) ? '' : ' title="' . htmlspecialchars($block['title'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE, 'UTF-8') . '"')
|
||||||
|
. '>' . $this->renderAbsy($block['text']) . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderImage($block)
|
||||||
|
{
|
||||||
|
if (isset($block['refkey'])) {
|
||||||
|
if (($ref = $this->lookupReference($block['refkey'])) !== false) {
|
||||||
|
$block = array_merge($block, $ref);
|
||||||
|
} else {
|
||||||
|
if (strncmp($block['orig'], '![', 2) === 0) {
|
||||||
|
return '![' . $this->renderAbsy($this->parseInline(substr($block['orig'], 2)));
|
||||||
|
}
|
||||||
|
return $block['orig'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '<img src="' . htmlspecialchars($block['url'], ENT_COMPAT | ENT_HTML401, 'UTF-8') . '"'
|
||||||
|
. ' alt="' . htmlspecialchars($block['text'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE, 'UTF-8') . '"'
|
||||||
|
. (empty($block['title']) ? '' : ' title="' . htmlspecialchars($block['title'], ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE, 'UTF-8') . '"')
|
||||||
|
. ($this->html5 ? '>' : ' />');
|
||||||
|
}
|
||||||
|
|
||||||
|
// references
|
||||||
|
|
||||||
|
protected function identifyReference($line)
|
||||||
|
{
|
||||||
|
return isset($line[0]) && ($line[0] === ' ' || $line[0] === '[') && preg_match('/^ {0,3}\[[^\[](.*?)\]:\s*([^\s]+?)(?:\s+[\'"](.+?)[\'"])?\s*$/', $line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume link references
|
||||||
|
*/
|
||||||
|
protected function consumeReference($lines, $current)
|
||||||
|
{
|
||||||
|
while (isset($lines[$current]) && preg_match('/^ {0,3}\[(.+?)\]:\s*(.+?)(?:\s+[\(\'"](.+?)[\)\'"])?\s*$/', $lines[$current], $matches)) {
|
||||||
|
$label = strtolower($matches[1]);
|
||||||
|
|
||||||
|
$this->references[$label] = [
|
||||||
|
'url' => $this->replaceEscape($matches[2]),
|
||||||
|
];
|
||||||
|
if (isset($matches[3])) {
|
||||||
|
$this->references[$label]['title'] = $matches[3];
|
||||||
|
} else {
|
||||||
|
// title may be on the next line
|
||||||
|
if (isset($lines[$current + 1]) && preg_match('/^\s+[\(\'"](.+?)[\)\'"]\s*$/', $lines[$current + 1], $matches)) {
|
||||||
|
$this->references[$label]['title'] = $matches[1];
|
||||||
|
$current++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$current++;
|
||||||
|
}
|
||||||
|
return [false, --$current];
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseInline($text);
|
||||||
|
abstract protected function renderAbsy($blocks);
|
||||||
|
}
|
||||||
40
core/lib/composer/vendor/cebe/markdown/inline/StrikeoutTrait.php
vendored
Normal file
40
core/lib/composer/vendor/cebe/markdown/inline/StrikeoutTrait.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\inline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds strikeout inline elements
|
||||||
|
*/
|
||||||
|
trait StrikeoutTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parses the strikethrough feature.
|
||||||
|
* @marker ~~
|
||||||
|
*/
|
||||||
|
protected function parseStrike($markdown)
|
||||||
|
{
|
||||||
|
if (preg_match('/^~~(.+?)~~/', $markdown, $matches)) {
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'strike',
|
||||||
|
$this->parseInline($matches[1])
|
||||||
|
],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [['text', $markdown[0] . $markdown[1]], 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderStrike($block)
|
||||||
|
{
|
||||||
|
return '<del>' . $this->renderAbsy($block[1]) . '</del>';
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function parseInline($text);
|
||||||
|
abstract protected function renderAbsy($blocks);
|
||||||
|
}
|
||||||
50
core/lib/composer/vendor/cebe/markdown/inline/UrlLinkTrait.php
vendored
Normal file
50
core/lib/composer/vendor/cebe/markdown/inline/UrlLinkTrait.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\inline;
|
||||||
|
|
||||||
|
// work around https://github.com/facebook/hhvm/issues/1120
|
||||||
|
defined('ENT_HTML401') || define('ENT_HTML401', 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds auto linking for URLs
|
||||||
|
*/
|
||||||
|
trait UrlLinkTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parses urls and adds auto linking feature.
|
||||||
|
* @marker http
|
||||||
|
* @marker ftp
|
||||||
|
*/
|
||||||
|
protected function parseUrl($markdown)
|
||||||
|
{
|
||||||
|
$pattern = <<<REGEXP
|
||||||
|
/(?(R) # in case of recursion match parentheses
|
||||||
|
\(((?>[^\s()]+)|(?R))*\)
|
||||||
|
| # else match a link with title
|
||||||
|
^(https?|ftp):\/\/(([^\s<>()]+)|(?R))+(?<![\.,:;\'"!\?\s])
|
||||||
|
)/x
|
||||||
|
REGEXP;
|
||||||
|
|
||||||
|
if (!in_array('parseLink', $this->context) && preg_match($pattern, $markdown, $matches)) {
|
||||||
|
return [
|
||||||
|
['autoUrl', $matches[0]],
|
||||||
|
strlen($matches[0])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [['text', substr($markdown, 0, 4)], 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderAutoUrl($block)
|
||||||
|
{
|
||||||
|
$href = htmlspecialchars($block[1], ENT_COMPAT | ENT_HTML401, 'UTF-8');
|
||||||
|
$decodedUrl = urldecode($block[1]);
|
||||||
|
$secureUrlText = preg_match('//u', $decodedUrl) ? $decodedUrl : $block[1];
|
||||||
|
$text = htmlspecialchars($secureUrlText, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||||
|
return "<a href=\"$href\">$text</a>";
|
||||||
|
}
|
||||||
|
}
|
||||||
27
core/lib/composer/vendor/cebe/markdown/phpunit.xml.dist
vendored
Normal file
27
core/lib/composer/vendor/cebe/markdown/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<phpunit bootstrap="./tests/bootstrap.php"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
stopOnFailure="false">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Markdown Test Suite">
|
||||||
|
<file>./tests/ParserTest.php</file>
|
||||||
|
|
||||||
|
<file>./tests/MarkdownTest.php</file>
|
||||||
|
<file>./tests/MarkdownOLStartNumTest.php</file>
|
||||||
|
|
||||||
|
<file>./tests/GithubMarkdownTest.php</file>
|
||||||
|
|
||||||
|
<file>./tests/MarkdownExtraTest.php</file>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<filter>
|
||||||
|
<blacklist>
|
||||||
|
<directory>./vendor</directory>
|
||||||
|
<directory>./tests</directory>
|
||||||
|
</blacklist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
||||||
|
|
||||||
115
core/lib/composer/vendor/cebe/markdown/tests/BaseMarkdownTest.php
vendored
Normal file
115
core/lib/composer/vendor/cebe/markdown/tests/BaseMarkdownTest.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\tests;
|
||||||
|
|
||||||
|
use cebe\markdown\Parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all Test cases.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
*/
|
||||||
|
abstract class BaseMarkdownTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $outputFileExtension = '.html';
|
||||||
|
|
||||||
|
abstract public function getDataPaths();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Parser
|
||||||
|
*/
|
||||||
|
abstract public function createMarkdown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataFiles
|
||||||
|
*/
|
||||||
|
public function testParse($path, $file)
|
||||||
|
{
|
||||||
|
list($markdown, $html) = $this->getTestData($path, $file);
|
||||||
|
// Different OS line endings should not affect test
|
||||||
|
$html = str_replace(["\r\n", "\n\r", "\r"], "\n", $html);
|
||||||
|
|
||||||
|
$m = $this->createMarkdown();
|
||||||
|
$this->assertEquals($html, $m->parse($markdown));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUtf8()
|
||||||
|
{
|
||||||
|
$this->assertSame("<p>абвгдеёжзийклмнопрстуфхцчшщъыьэюя</p>\n", $this->createMarkdown()->parse('абвгдеёжзийклмнопрстуфхцчшщъыьэюя'));
|
||||||
|
$this->assertSame("<p>there is a charater, 配</p>\n", $this->createMarkdown()->parse('there is a charater, 配'));
|
||||||
|
$this->assertSame("<p>Arabic Latter \"م (M)\"</p>\n", $this->createMarkdown()->parse('Arabic Latter "م (M)"'));
|
||||||
|
$this->assertSame("<p>電腦</p>\n", $this->createMarkdown()->parse('電腦'));
|
||||||
|
|
||||||
|
$this->assertSame('абвгдеёжзийклмнопрстуфхцчшщъыьэюя', $this->createMarkdown()->parseParagraph('абвгдеёжзийклмнопрстуфхцчшщъыьэюя'));
|
||||||
|
$this->assertSame('there is a charater, 配', $this->createMarkdown()->parseParagraph('there is a charater, 配'));
|
||||||
|
$this->assertSame('Arabic Latter "م (M)"', $this->createMarkdown()->parseParagraph('Arabic Latter "م (M)"'));
|
||||||
|
$this->assertSame('電腦', $this->createMarkdown()->parseParagraph('電腦'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidUtf8()
|
||||||
|
{
|
||||||
|
$m = $this->createMarkdown();
|
||||||
|
$this->assertEquals("<p><code><3E></code></p>\n", $m->parse("`\x80`"));
|
||||||
|
$this->assertEquals('<code><3E></code>', $m->parseParagraph("`\x80`"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pregData()
|
||||||
|
{
|
||||||
|
// http://en.wikipedia.org/wiki/Newline#Representations
|
||||||
|
return [
|
||||||
|
["a\r\nb", "a\nb"],
|
||||||
|
["a\n\rb", "a\nb"], // Acorn BBC and RISC OS spooled text output :)
|
||||||
|
["a\nb", "a\nb"],
|
||||||
|
["a\rb", "a\nb"],
|
||||||
|
|
||||||
|
["a\n\nb", "a\n\nb", "a</p>\n<p>b"],
|
||||||
|
["a\r\rb", "a\n\nb", "a</p>\n<p>b"],
|
||||||
|
["a\n\r\n\rb", "a\n\nb", "a</p>\n<p>b"], // Acorn BBC and RISC OS spooled text output :)
|
||||||
|
["a\r\n\r\nb", "a\n\nb", "a</p>\n<p>b"],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider pregData
|
||||||
|
*/
|
||||||
|
public function testPregReplaceR($input, $exptected, $pexpect = null)
|
||||||
|
{
|
||||||
|
$this->assertSame($exptected, $this->createMarkdown()->parseParagraph($input));
|
||||||
|
$this->assertSame($pexpect === null ? "<p>$exptected</p>\n" : "<p>$pexpect</p>\n", $this->createMarkdown()->parse($input));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTestData($path, $file)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
file_get_contents($this->getDataPaths()[$path] . '/' . $file . '.md'),
|
||||||
|
file_get_contents($this->getDataPaths()[$path] . '/' . $file . $this->outputFileExtension),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataFiles()
|
||||||
|
{
|
||||||
|
$files = [];
|
||||||
|
foreach ($this->getDataPaths() as $name => $src) {
|
||||||
|
$handle = opendir($src);
|
||||||
|
if ($handle === false) {
|
||||||
|
throw new \Exception('Unable to open directory: ' . $src);
|
||||||
|
}
|
||||||
|
while (($file = readdir($handle)) !== false) {
|
||||||
|
if ($file === '.' || $file === '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (substr($file, -3, 3) === '.md' && file_exists($src . '/' . substr($file, 0, -3) . $this->outputFileExtension)) {
|
||||||
|
$files[] = [$name, substr($file, 0, -3)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir($handle);
|
||||||
|
}
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
core/lib/composer/vendor/cebe/markdown/tests/GithubMarkdownTest.php
vendored
Normal file
80
core/lib/composer/vendor/cebe/markdown/tests/GithubMarkdownTest.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\tests;
|
||||||
|
|
||||||
|
use cebe\markdown\GithubMarkdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for the github flavored markdown.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
* @group github
|
||||||
|
*/
|
||||||
|
class GithubMarkdownTest extends BaseMarkdownTest
|
||||||
|
{
|
||||||
|
public function createMarkdown()
|
||||||
|
{
|
||||||
|
return new GithubMarkdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDataPaths()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'markdown-data' => __DIR__ . '/markdown-data',
|
||||||
|
'github-data' => __DIR__ . '/github-data',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNewlines()
|
||||||
|
{
|
||||||
|
$markdown = $this->createMarkdown();
|
||||||
|
$this->assertEquals("This is text<br />\nnewline\nnewline.", $markdown->parseParagraph("This is text \nnewline\nnewline."));
|
||||||
|
$markdown->enableNewlines = true;
|
||||||
|
$this->assertEquals("This is text<br />\nnewline<br />\nnewline.", $markdown->parseParagraph("This is text \nnewline\nnewline."));
|
||||||
|
|
||||||
|
$this->assertEquals("<p>This is text</p>\n<p>newline<br />\nnewline.</p>\n", $markdown->parse("This is text\n\nnewline\nnewline."));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataFiles()
|
||||||
|
{
|
||||||
|
$files = parent::dataFiles();
|
||||||
|
foreach($files as $i => $f) {
|
||||||
|
// skip files that are different in github MD
|
||||||
|
if ($f[0] === 'markdown-data' && (
|
||||||
|
$f[1] === 'list-marker-in-paragraph' ||
|
||||||
|
$f[1] === 'dense-block-markers'
|
||||||
|
)) {
|
||||||
|
unset($files[$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testKeepZeroAlive()
|
||||||
|
{
|
||||||
|
$parser = $this->createMarkdown();
|
||||||
|
|
||||||
|
$this->assertEquals("0", $parser->parseParagraph("0"));
|
||||||
|
$this->assertEquals("<p>0</p>\n", $parser->parse("0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAutoLinkLabelingWithEncodedUrl()
|
||||||
|
{
|
||||||
|
$parser = $this->createMarkdown();
|
||||||
|
|
||||||
|
$utfText = "\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a";
|
||||||
|
$utfNaturalUrl = "http://example.com/" . $utfText;
|
||||||
|
$utfEncodedUrl = "http://example.com/" . urlencode($utfText);
|
||||||
|
$eucEncodedUrl = "http://example.com/" . urlencode(mb_convert_encoding($utfText, 'EUC-JP', 'UTF-8'));
|
||||||
|
|
||||||
|
$this->assertStringEndsWith(">{$utfNaturalUrl}</a>", $parser->parseParagraph($utfNaturalUrl), "Natural UTF-8 URL needs no conversion.");
|
||||||
|
$this->assertStringEndsWith(">{$utfNaturalUrl}</a>", $parser->parseParagraph($utfEncodedUrl), "Encoded UTF-8 URL will be converted to readable format.");
|
||||||
|
$this->assertStringEndsWith(">{$eucEncodedUrl}</a>", $parser->parseParagraph($eucEncodedUrl), "Non UTF-8 URL should never be converted.");
|
||||||
|
// See: \cebe\markdown\inline\UrlLinkTrait::renderAutoUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
24
core/lib/composer/vendor/cebe/markdown/tests/MarkdownExtraTest.php
vendored
Normal file
24
core/lib/composer/vendor/cebe/markdown/tests/MarkdownExtraTest.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace cebe\markdown\tests;
|
||||||
|
use cebe\markdown\MarkdownExtra;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
* @group extra
|
||||||
|
*/
|
||||||
|
class MarkdownExtraTest extends BaseMarkdownTest
|
||||||
|
{
|
||||||
|
public function createMarkdown()
|
||||||
|
{
|
||||||
|
return new MarkdownExtra();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDataPaths()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'markdown-data' => __DIR__ . '/markdown-data',
|
||||||
|
'extra-data' => __DIR__ . '/extra-data',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
32
core/lib/composer/vendor/cebe/markdown/tests/MarkdownOLStartNumTest.php
vendored
Normal file
32
core/lib/composer/vendor/cebe/markdown/tests/MarkdownOLStartNumTest.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\tests;
|
||||||
|
|
||||||
|
use cebe\markdown\Markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test support ordered lists at arbitrary number(`start` html attribute)
|
||||||
|
* @author Maxim Hodyrew <maximkou@gmail.com>
|
||||||
|
* @group default
|
||||||
|
*/
|
||||||
|
class MarkdownOLStartNumTest extends BaseMarkdownTest
|
||||||
|
{
|
||||||
|
public function createMarkdown()
|
||||||
|
{
|
||||||
|
$markdown = new Markdown();
|
||||||
|
$markdown->keepListStartNumber = true;
|
||||||
|
return $markdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDataPaths()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'markdown-data' => __DIR__ . '/markdown-ol-start-num-data',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
60
core/lib/composer/vendor/cebe/markdown/tests/MarkdownTest.php
vendored
Normal file
60
core/lib/composer/vendor/cebe/markdown/tests/MarkdownTest.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\tests;
|
||||||
|
|
||||||
|
use cebe\markdown\Markdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for traditional markdown.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
* @group default
|
||||||
|
*/
|
||||||
|
class MarkdownTest extends BaseMarkdownTest
|
||||||
|
{
|
||||||
|
public function createMarkdown()
|
||||||
|
{
|
||||||
|
return new Markdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDataPaths()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'markdown-data' => __DIR__ . '/markdown-data',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEdgeCases()
|
||||||
|
{
|
||||||
|
$this->assertEquals("<p>&</p>\n", $this->createMarkdown()->parse('&'));
|
||||||
|
$this->assertEquals("<p><</p>\n", $this->createMarkdown()->parse('<'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testKeepZeroAlive()
|
||||||
|
{
|
||||||
|
$parser = $this->createMarkdown();
|
||||||
|
|
||||||
|
$this->assertEquals("0", $parser->parseParagraph("0"));
|
||||||
|
$this->assertEquals("<p>0</p>\n", $parser->parse("0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAutoLinkLabelingWithEncodedUrl()
|
||||||
|
{
|
||||||
|
$parser = $this->createMarkdown();
|
||||||
|
|
||||||
|
$utfText = "\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a";
|
||||||
|
$utfNaturalUrl = "http://example.com/" . $utfText;
|
||||||
|
$utfEncodedUrl = "http://example.com/" . urlencode($utfText);
|
||||||
|
$eucEncodedUrl = "http://example.com/" . urlencode(mb_convert_encoding($utfText, 'EUC-JP', 'UTF-8'));
|
||||||
|
|
||||||
|
$this->assertStringEndsWith(">{$utfNaturalUrl}</a>", $parser->parseParagraph("<{$utfNaturalUrl}>"), "Natural UTF-8 URL needs no conversion.");
|
||||||
|
$this->assertStringEndsWith(">{$utfNaturalUrl}</a>", $parser->parseParagraph("<{$utfEncodedUrl}>"), "Encoded UTF-8 URL will be converted to readable format.");
|
||||||
|
$this->assertStringEndsWith(">{$eucEncodedUrl}</a>", $parser->parseParagraph("<{$eucEncodedUrl}>"), "Non UTF-8 URL should never be converted.");
|
||||||
|
// See: \cebe\markdown\inline\LinkTrait::renderUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
94
core/lib/composer/vendor/cebe/markdown/tests/ParserTest.php
vendored
Normal file
94
core/lib/composer/vendor/cebe/markdown/tests/ParserTest.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (c) 2014 Carsten Brandt
|
||||||
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE
|
||||||
|
* @link https://github.com/cebe/markdown#readme
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace cebe\markdown\tests;
|
||||||
|
|
||||||
|
use cebe\markdown\Parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for the parser base class.
|
||||||
|
*
|
||||||
|
* @author Carsten Brandt <mail@cebe.cc>
|
||||||
|
* @group default
|
||||||
|
*/
|
||||||
|
class ParserTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testMarkerOrder()
|
||||||
|
{
|
||||||
|
$parser = new TestParser();
|
||||||
|
$parser->markers = [
|
||||||
|
'[' => 'parseMarkerA',
|
||||||
|
'[[' => 'parseMarkerB',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertEquals("<p>Result is A</p>\n", $parser->parse('Result is [abc]'));
|
||||||
|
$this->assertEquals("<p>Result is B</p>\n", $parser->parse('Result is [[abc]]'));
|
||||||
|
$this->assertEquals('Result is A', $parser->parseParagraph('Result is [abc]'));
|
||||||
|
$this->assertEquals('Result is B', $parser->parseParagraph('Result is [[abc]]'));
|
||||||
|
|
||||||
|
$parser = new TestParser();
|
||||||
|
$parser->markers = [
|
||||||
|
'[[' => 'parseMarkerB',
|
||||||
|
'[' => 'parseMarkerA',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertEquals("<p>Result is A</p>\n", $parser->parse('Result is [abc]'));
|
||||||
|
$this->assertEquals("<p>Result is B</p>\n", $parser->parse('Result is [[abc]]'));
|
||||||
|
$this->assertEquals('Result is A', $parser->parseParagraph('Result is [abc]'));
|
||||||
|
$this->assertEquals('Result is B', $parser->parseParagraph('Result is [[abc]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMaxNestingLevel()
|
||||||
|
{
|
||||||
|
$parser = new TestParser();
|
||||||
|
$parser->markers = [
|
||||||
|
'[' => 'parseMarkerC',
|
||||||
|
];
|
||||||
|
|
||||||
|
$parser->maximumNestingLevel = 3;
|
||||||
|
$this->assertEquals("(C-a(C-b(C-c)))", $parser->parseParagraph('[a[b[c]]]'));
|
||||||
|
$parser->maximumNestingLevel = 2;
|
||||||
|
$this->assertEquals("(C-a(C-b[c]))", $parser->parseParagraph('[a[b[c]]]'));
|
||||||
|
$parser->maximumNestingLevel = 1;
|
||||||
|
$this->assertEquals("(C-a[b[c]])", $parser->parseParagraph('[a[b[c]]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testKeepZeroAlive()
|
||||||
|
{
|
||||||
|
$parser = new TestParser();
|
||||||
|
|
||||||
|
$this->assertEquals("0", $parser->parseParagraph("0"));
|
||||||
|
$this->assertEquals("<p>0</p>\n", $parser->parse("0"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestParser extends Parser
|
||||||
|
{
|
||||||
|
public $markers = [];
|
||||||
|
|
||||||
|
protected function inlineMarkers()
|
||||||
|
{
|
||||||
|
return $this->markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseMarkerA($text)
|
||||||
|
{
|
||||||
|
return [['text', 'A'], strrpos($text, ']') + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseMarkerB($text)
|
||||||
|
{
|
||||||
|
return [['text', 'B'], strrpos($text, ']') + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseMarkerC($text)
|
||||||
|
{
|
||||||
|
$terminatingMarkerPos = strrpos($text, ']');
|
||||||
|
$inside = $this->parseInline(substr($text, 1, $terminatingMarkerPos - 1));
|
||||||
|
return [['text', '(C-' . $this->renderAbsy($inside) . ')'], $terminatingMarkerPos + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
5
core/lib/composer/vendor/cebe/markdown/tests/bootstrap.php
vendored
Normal file
5
core/lib/composer/vendor/cebe/markdown/tests/bootstrap.php
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
|
||||||
|
require(__DIR__ . '/../vendor/autoload.php');
|
||||||
|
}
|
||||||
82
core/lib/composer/vendor/cebe/markdown/tests/extra-data/code_in_lists.html
vendored
Normal file
82
core/lib/composer/vendor/cebe/markdown/tests/extra-data/code_in_lists.html
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code>```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code> bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code> bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code> bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code>bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
94
core/lib/composer/vendor/cebe/markdown/tests/extra-data/code_in_lists.md
vendored
Normal file
94
core/lib/composer/vendor/cebe/markdown/tests/extra-data/code_in_lists.md
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
17
core/lib/composer/vendor/cebe/markdown/tests/extra-data/fenced-code.html
vendored
Normal file
17
core/lib/composer/vendor/cebe/markdown/tests/extra-data/fenced-code.html
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<pre><code>
|
||||||
|
fenced code block
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>
|
||||||
|
fenced with tildes
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>long fence
|
||||||
|
|
||||||
|
```
|
||||||
|
code about code
|
||||||
|
```
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
<pre><code class="html" id="test">fenced code block
|
||||||
|
</code></pre>
|
||||||
24
core/lib/composer/vendor/cebe/markdown/tests/extra-data/fenced-code.md
vendored
Normal file
24
core/lib/composer/vendor/cebe/markdown/tests/extra-data/fenced-code.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
```
|
||||||
|
|
||||||
|
fenced code block
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
fenced with tildes
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
``````````
|
||||||
|
long fence
|
||||||
|
|
||||||
|
```
|
||||||
|
code about code
|
||||||
|
```
|
||||||
|
|
||||||
|
``````````
|
||||||
|
|
||||||
|
``` .html #test
|
||||||
|
fenced code block
|
||||||
|
```
|
||||||
8
core/lib/composer/vendor/cebe/markdown/tests/extra-data/non-tables.html
vendored
Normal file
8
core/lib/composer/vendor/cebe/markdown/tests/extra-data/non-tables.html
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<h2>Non-tables</h2>
|
||||||
|
<p>This line contains two pipes but is not a table. [[yii\widgets\DetailView|DetailView]] widget displays the details of a single data [[yii\widgets\DetailView::$model|model]].</p>
|
||||||
|
<p>the line above contains a space.</p>
|
||||||
|
<p>looks | like | head
|
||||||
|
-:</p>
|
||||||
|
<p>looks | like | head
|
||||||
|
-:
|
||||||
|
a</p>
|
||||||
13
core/lib/composer/vendor/cebe/markdown/tests/extra-data/non-tables.md
vendored
Normal file
13
core/lib/composer/vendor/cebe/markdown/tests/extra-data/non-tables.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Non-tables
|
||||||
|
----------
|
||||||
|
|
||||||
|
This line contains two pipes but is not a table. [[yii\widgets\DetailView|DetailView]] widget displays the details of a single data [[yii\widgets\DetailView::$model|model]].
|
||||||
|
|
||||||
|
the line above contains a space.
|
||||||
|
|
||||||
|
looks | like | head
|
||||||
|
-:
|
||||||
|
|
||||||
|
looks | like | head
|
||||||
|
-:
|
||||||
|
a
|
||||||
12
core/lib/composer/vendor/cebe/markdown/tests/extra-data/special-attributes.html
vendored
Normal file
12
core/lib/composer/vendor/cebe/markdown/tests/extra-data/special-attributes.html
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<h1 id="header1">Header 1</h1>
|
||||||
|
<h2 id="header2">Header 2</h2>
|
||||||
|
<h2 class="main">The Site</h2>
|
||||||
|
<h2 class="main shine" id="the-site">The Site</h2>
|
||||||
|
<p><a href="url" id="id1" class="class">link</a>
|
||||||
|
<img src="url" alt="img" id="id2" class="class" /></p>
|
||||||
|
<p><a href="http://url.de/" title="optional title" id="id" class="class">link</a> or <a href="http://url.de/" title="optional title" id="id" class="class">linkref</a>
|
||||||
|
<img src="http://url.de/" alt="img" title="optional title" id="id" class="class" /></p>
|
||||||
|
<p>this is just normal text {.main .shine #the-site}</p>
|
||||||
|
<p>some { brackets</p>
|
||||||
|
<p>some } brackets</p>
|
||||||
|
<p>some { } brackets</p>
|
||||||
25
core/lib/composer/vendor/cebe/markdown/tests/extra-data/special-attributes.md
vendored
Normal file
25
core/lib/composer/vendor/cebe/markdown/tests/extra-data/special-attributes.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Header 1 {#header1}
|
||||||
|
========
|
||||||
|
|
||||||
|
## Header 2 ## {#header2}
|
||||||
|
|
||||||
|
## The Site ## {.main}
|
||||||
|
|
||||||
|
## The Site ## {.main .shine #the-site}
|
||||||
|
|
||||||
|
[link](url){#id1 .class}
|
||||||
|
{#id2 .class}
|
||||||
|
|
||||||
|
|
||||||
|
[link][linkref] or [linkref]
|
||||||
|
![img][linkref]
|
||||||
|
|
||||||
|
[linkref]: http://url.de/ "optional title" {#id .class}
|
||||||
|
|
||||||
|
this is just normal text {.main .shine #the-site}
|
||||||
|
|
||||||
|
some { brackets
|
||||||
|
|
||||||
|
some } brackets
|
||||||
|
|
||||||
|
some { } brackets
|
||||||
219
core/lib/composer/vendor/cebe/markdown/tests/extra-data/tables.html
vendored
Normal file
219
core/lib/composer/vendor/cebe/markdown/tests/extra-data/tables.html
vendored
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
<h2>Tables</h2>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>First Header</th><th>Second Header</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Content Cell</td><td>Content Cell</td></tr>
|
||||||
|
<tr><td>Content Cell</td><td>Content Cell</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>First Header</th><th>Second Header</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Content Cell</td><td>Content Cell</td></tr>
|
||||||
|
<tr><td>Content Cell</td><td>Content Cell</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Name</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Help</td><td>Display the help window.</td></tr>
|
||||||
|
<tr><td>Close</td><td>Closes a window</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Name</th><th>Description</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Help</td><td><strong>Display the</strong> help window.</td></tr>
|
||||||
|
<tr><td>Close</td><td><em>Closes</em> a window</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Default-Align</th><th align="left">Left-Aligned</th><th align="center">Center Aligned</th><th align="right">Right Aligned</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td align="left">col 3 is</td><td align="center">some wordy text</td><td align="right">$1600</td></tr>
|
||||||
|
<tr><td>2</td><td align="left">col 2 is</td><td align="center">centered</td><td align="right">$12</td></tr>
|
||||||
|
<tr><td>3</td><td align="left">zebra stripes</td><td align="center">are neat</td><td align="right">$1</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Simple</th><th>Table</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td></tr>
|
||||||
|
<tr><td>3</td><td>4</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Simple</th><th>Table</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td></tr>
|
||||||
|
<tr><td>3</td><td>4</td></tr>
|
||||||
|
<tr><td>3</td><td>4 |</td></tr>
|
||||||
|
<tr><td>3</td><td>4 \</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Check https://github.com/erusev/parsedown/issues/184 for the following:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Foo</th><th>Bar</th><th>State</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><code>Code | Pipe</code></td><td>Broken</td><td>Blank</td></tr>
|
||||||
|
<tr><td><code>Escaped Code \| Pipe</code></td><td>Broken</td><td>Blank</td></tr>
|
||||||
|
<tr><td>Escaped | Pipe</td><td>Broken</td><td>Blank</td></tr>
|
||||||
|
<tr><td>Escaped \</td><td>Pipe</td><td>Broken</td><td>Blank</td></tr>
|
||||||
|
<tr><td>Escaped \</td><td>Pipe</td><td>Broken</td><td>Blank</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th align="left">Simple</th><th>Table</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td align="left">3</td><td>4</td></tr>
|
||||||
|
<tr><td align="left">3</td><td>4</td></tr>
|
||||||
|
<tr><td align="left">5</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Mixed</th><th>Table</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td></tr>
|
||||||
|
<tr><td>3</td><td>4</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Mixed</th><th>Table</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td></tr>
|
||||||
|
<tr><td>3</td><td>4</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Mixed</th><th>Table</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td></tr>
|
||||||
|
<tr><td>3</td><td>4</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>some text</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>single col</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td></tr>
|
||||||
|
<tr><td>2</td></tr>
|
||||||
|
<tr><td>3</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Table</th><th>With</th><th>Empty</th><th>Cells</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td></td><td></td><td></td><td></td></tr>
|
||||||
|
<tr><td>a</td><td></td><td>b</td><td></td></tr>
|
||||||
|
<tr><td></td><td>a</td><td></td><td>b</td></tr>
|
||||||
|
<tr><td>a</td><td></td><td></td><td>b</td></tr>
|
||||||
|
<tr><td></td><td>a</td><td>b</td><td></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th></th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th></th><th></th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td></td><td></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Table</th><th>Indentation</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A</td><td>B</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Table</th><th>Indentation</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A</td><td>B</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Table</th><th>Indentation</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>A</td><td>B</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<pre><code>| Table | Indentation |
|
||||||
|
</code></pre>
|
||||||
|
<p> | ----- | ---- |
|
||||||
|
| A | B |</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th align="left">Table</th><th>Indentation</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<pre><code>| A | B |
|
||||||
|
</code></pre>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>Item</th><th align="right">Value</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Computer</td><td align="right">$1600</td></tr>
|
||||||
|
<tr><td>Phone</td><td align="right">$12</td></tr>
|
||||||
|
<tr><td>Pipe</td><td align="right">$1</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th align="center">a</th><th align="center">b</th><th align="center">c</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td align="center">1</td><td align="center">2</td><td align="center">3</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th align="left">a</th><th align="center">b</th><th align="left">c</th><th align="center">d</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td align="left">1</td><td align="center">2</td><td align="left">3</td><td align="center">4</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
130
core/lib/composer/vendor/cebe/markdown/tests/extra-data/tables.md
vendored
Normal file
130
core/lib/composer/vendor/cebe/markdown/tests/extra-data/tables.md
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
Tables
|
||||||
|
------
|
||||||
|
|
||||||
|
First Header | Second Header
|
||||||
|
------------- | -------------
|
||||||
|
Content Cell | Content Cell
|
||||||
|
Content Cell | Content Cell
|
||||||
|
|
||||||
|
| First Header | Second Header |
|
||||||
|
| ------------- | ------------- |
|
||||||
|
| Content Cell | Content Cell |
|
||||||
|
| Content Cell | Content Cell |
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ------------- | ----------- |
|
||||||
|
| Help | Display the help window.|
|
||||||
|
| Close | Closes a window |
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ------------- | ----------- |
|
||||||
|
| Help | **Display the** help window.|
|
||||||
|
| Close | _Closes_ a window |
|
||||||
|
|
||||||
|
| Default-Align | Left-Aligned | Center Aligned | Right Aligned |
|
||||||
|
| ------------- | :------------ |:---------------:| -----:|
|
||||||
|
| 1 | col 3 is | some wordy text | $1600 |
|
||||||
|
| 2 | col 2 is | centered | $12 |
|
||||||
|
| 3 | zebra stripes | are neat | $1 |
|
||||||
|
|
||||||
|
|
||||||
|
Simple | Table
|
||||||
|
------ | -----
|
||||||
|
1 | 2
|
||||||
|
3 | 4
|
||||||
|
|
||||||
|
| Simple | Table |
|
||||||
|
| ------ | ----- |
|
||||||
|
| 1 | 2 |
|
||||||
|
| 3 | 4 |
|
||||||
|
| 3 | 4 \|
|
||||||
|
| 3 | 4 \\|
|
||||||
|
|
||||||
|
Check https://github.com/erusev/parsedown/issues/184 for the following:
|
||||||
|
|
||||||
|
Foo | Bar | State
|
||||||
|
------ | ------ | -----
|
||||||
|
`Code | Pipe` | Broken | Blank
|
||||||
|
`Escaped Code \| Pipe` | Broken | Blank
|
||||||
|
Escaped \| Pipe | Broken | Blank
|
||||||
|
Escaped \\| Pipe | Broken | Blank
|
||||||
|
Escaped \\ | Pipe | Broken | Blank
|
||||||
|
|
||||||
|
| Simple | Table |
|
||||||
|
| :----- | ----- |
|
||||||
|
| 3 | 4 |
|
||||||
|
3 | 4
|
||||||
|
5
|
||||||
|
|
||||||
|
Mixed | Table
|
||||||
|
------ | -----
|
||||||
|
| 1 | 2
|
||||||
|
3 | 4
|
||||||
|
|
||||||
|
| Mixed | Table
|
||||||
|
------ | -----
|
||||||
|
| 1 | 2
|
||||||
|
3 | 4
|
||||||
|
|
||||||
|
Mixed | Table
|
||||||
|
|------ | ----- |
|
||||||
|
1 | 2
|
||||||
|
| 3 | 4 |
|
||||||
|
|
||||||
|
some text
|
||||||
|
|
||||||
|
| single col |
|
||||||
|
| -- | -- |
|
||||||
|
| 1 |
|
||||||
|
2
|
||||||
|
3
|
||||||
|
|
||||||
|
| Table | With | Empty | Cells |
|
||||||
|
| ----- | ---- | ----- | ----- |
|
||||||
|
| | | | |
|
||||||
|
| a | | b | |
|
||||||
|
| | a | | b |
|
||||||
|
| a | | | b |
|
||||||
|
| | a | b | |
|
||||||
|
|
||||||
|
|
|
||||||
|
-- | --
|
||||||
|
|
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| - | - |
|
||||||
|
| | |
|
||||||
|
|
||||||
|
| Table | Indentation |
|
||||||
|
| ----- | ---- |
|
||||||
|
| A | B |
|
||||||
|
|
||||||
|
| Table | Indentation |
|
||||||
|
| ----- | ---- |
|
||||||
|
| A | B |
|
||||||
|
|
||||||
|
| Table | Indentation |
|
||||||
|
| ----- | ---- |
|
||||||
|
| A | B |
|
||||||
|
|
||||||
|
| Table | Indentation |
|
||||||
|
| ----- | ---- |
|
||||||
|
| A | B |
|
||||||
|
|
||||||
|
| Table | Indentation |
|
||||||
|
| :----- | ---- |
|
||||||
|
| A | B |
|
||||||
|
|
||||||
|
| Item | Value |
|
||||||
|
| --------- | -----:|
|
||||||
|
| Computer | $1600 |
|
||||||
|
| Phone | $12 |
|
||||||
|
| Pipe | $1 |
|
||||||
|
|
||||||
|
| a | b | c |
|
||||||
|
|:-:|:-:|:-:|
|
||||||
|
| 1 | 2 | 3 |
|
||||||
|
|
||||||
|
| a | b | c | d |
|
||||||
|
|:--|:-:|:--|:-:|
|
||||||
|
| 1 | 2 | 3 | 4 |
|
||||||
8
core/lib/composer/vendor/cebe/markdown/tests/extra-data/test_precedence.html
vendored
Normal file
8
core/lib/composer/vendor/cebe/markdown/tests/extra-data/test_precedence.html
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<p>Not a headline but a code block:</p>
|
||||||
|
<pre><code>---
|
||||||
|
</code></pre>
|
||||||
|
<p>Not a headline but two HR:</p>
|
||||||
|
<hr />
|
||||||
|
<hr />
|
||||||
|
<hr />
|
||||||
|
<hr />
|
||||||
14
core/lib/composer/vendor/cebe/markdown/tests/extra-data/test_precedence.md
vendored
Normal file
14
core/lib/composer/vendor/cebe/markdown/tests/extra-data/test_precedence.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Not a headline but a code block:
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Not a headline but two HR:
|
||||||
|
|
||||||
|
***
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
***
|
||||||
|
|
||||||
82
core/lib/composer/vendor/cebe/markdown/tests/github-data/code_in_lists.html
vendored
Normal file
82
core/lib/composer/vendor/cebe/markdown/tests/github-data/code_in_lists.html
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code>```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code> bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code> bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code> bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<ol>
|
||||||
|
<li><p>foo</p>
|
||||||
|
<pre><code>bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
94
core/lib/composer/vendor/cebe/markdown/tests/github-data/code_in_lists.md
vendored
Normal file
94
core/lib/composer/vendor/cebe/markdown/tests/github-data/code_in_lists.md
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
1. foo
|
||||||
|
|
||||||
|
```
|
||||||
|
bar
|
||||||
|
|
||||||
|
blah
|
||||||
|
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
foo
|
||||||
|
|
||||||
|
bar
|
||||||
|
```
|
||||||
5
core/lib/composer/vendor/cebe/markdown/tests/github-data/del.html
vendored
Normal file
5
core/lib/composer/vendor/cebe/markdown/tests/github-data/del.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<p>this is <del>striked out</del> after</p>
|
||||||
|
<p><del>striked out</del></p>
|
||||||
|
<p>a line with ~~ in it ...</p>
|
||||||
|
<p>~~</p>
|
||||||
|
<p>~</p>
|
||||||
9
core/lib/composer/vendor/cebe/markdown/tests/github-data/del.md
vendored
Normal file
9
core/lib/composer/vendor/cebe/markdown/tests/github-data/del.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
this is ~~striked out~~ after
|
||||||
|
|
||||||
|
~~striked out~~
|
||||||
|
|
||||||
|
a line with ~~ in it ...
|
||||||
|
|
||||||
|
~~
|
||||||
|
|
||||||
|
~
|
||||||
52
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers.html
vendored
Normal file
52
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers.html
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<h1>this is to test dense blocks (no newlines between them)</h1>
|
||||||
|
<hr />
|
||||||
|
<h2>what is Markdown?</h2>
|
||||||
|
<p>see <a href="http://en.wikipedia.org/wiki/Markdown">Wikipedia</a></p>
|
||||||
|
<h2>a h2</h2>
|
||||||
|
<p>paragraph</p>
|
||||||
|
<p>this is a paragraph, not a headline or list
|
||||||
|
next line</p>
|
||||||
|
<ul>
|
||||||
|
<li>whoo</li>
|
||||||
|
</ul>
|
||||||
|
<p>par</p>
|
||||||
|
<pre><code>code
|
||||||
|
code
|
||||||
|
</code></pre>
|
||||||
|
<p>par</p>
|
||||||
|
<h3>Tasks list</h3>
|
||||||
|
<ul>
|
||||||
|
<li>list items</li>
|
||||||
|
</ul>
|
||||||
|
<h2>headline1</h2>
|
||||||
|
<blockquote><p>quote
|
||||||
|
quote</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2>headline2</h2>
|
||||||
|
<hr />
|
||||||
|
<h1>h1</h1>
|
||||||
|
<h2>h2</h2>
|
||||||
|
<hr />
|
||||||
|
<h3>h3</h3>
|
||||||
|
<ol>
|
||||||
|
<li>ol1</li>
|
||||||
|
<li>ol2</li>
|
||||||
|
</ol>
|
||||||
|
<h4>h4</h4>
|
||||||
|
<ul>
|
||||||
|
<li>listA</li>
|
||||||
|
<li>listB</li>
|
||||||
|
</ul>
|
||||||
|
<h5>h5</h5>
|
||||||
|
<h6>h6</h6>
|
||||||
|
<hr />
|
||||||
|
<hr />
|
||||||
|
<h2>changelog 1</h2>
|
||||||
|
<ul>
|
||||||
|
<li>17-Feb-2013 re-design</li>
|
||||||
|
</ul>
|
||||||
|
<hr />
|
||||||
|
<h2>changelog 2</h2>
|
||||||
|
<ul>
|
||||||
|
<li>17-Feb-2013 re-design</li>
|
||||||
|
</ul>
|
||||||
56
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers.md
vendored
Normal file
56
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers.md
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# this is to test dense blocks (no newlines between them)
|
||||||
|
|
||||||
|
----
|
||||||
|
## what is Markdown?
|
||||||
|
see [Wikipedia][]
|
||||||
|
|
||||||
|
a h2
|
||||||
|
----
|
||||||
|
paragraph
|
||||||
|
|
||||||
|
this is a paragraph, not a headline or list
|
||||||
|
next line
|
||||||
|
- whoo
|
||||||
|
|
||||||
|
par
|
||||||
|
code
|
||||||
|
code
|
||||||
|
par
|
||||||
|
|
||||||
|
### Tasks list
|
||||||
|
- list items
|
||||||
|
|
||||||
|
headline1
|
||||||
|
---------
|
||||||
|
> quote
|
||||||
|
> quote
|
||||||
|
|
||||||
|
[Wikipedia]: http://en.wikipedia.org/wiki/Markdown
|
||||||
|
headline2
|
||||||
|
---------
|
||||||
|
|
||||||
|
----
|
||||||
|
# h1
|
||||||
|
## h2
|
||||||
|
---
|
||||||
|
### h3
|
||||||
|
1. ol1
|
||||||
|
2. ol2
|
||||||
|
|
||||||
|
#### h4
|
||||||
|
- listA
|
||||||
|
- listB
|
||||||
|
|
||||||
|
##### h5
|
||||||
|
###### h6
|
||||||
|
--------
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## changelog 1
|
||||||
|
|
||||||
|
* 17-Feb-2013 re-design
|
||||||
|
|
||||||
|
----
|
||||||
|
## changelog 2
|
||||||
|
* 17-Feb-2013 re-design
|
||||||
23
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers2.html
vendored
Normal file
23
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers2.html
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<p>Now we need to set:</p>
|
||||||
|
<pre><code class="language-php">'session' => [
|
||||||
|
'cookieParams' => [
|
||||||
|
'path' => '/path1/',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
</code></pre>
|
||||||
|
<p>and</p>
|
||||||
|
<pre><code class="language-php">'session' => [
|
||||||
|
'cookieParams' => [
|
||||||
|
'path' => '/path2/',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
</code></pre>
|
||||||
|
<p>In the following starts a Blockquote:</p>
|
||||||
|
<blockquote><p>this is a blockquote</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>par</p>
|
||||||
|
<hr />
|
||||||
|
<p>par</p>
|
||||||
|
<p>This is some text</p>
|
||||||
|
<h1>Headline1</h1>
|
||||||
|
<p>more text</p>
|
||||||
27
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers2.md
vendored
Normal file
27
core/lib/composer/vendor/cebe/markdown/tests/github-data/dense-block-markers2.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Now we need to set:
|
||||||
|
```php
|
||||||
|
'session' => [
|
||||||
|
'cookieParams' => [
|
||||||
|
'path' => '/path1/',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
```
|
||||||
|
and
|
||||||
|
```php
|
||||||
|
'session' => [
|
||||||
|
'cookieParams' => [
|
||||||
|
'path' => '/path2/',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
In the following starts a Blockquote:
|
||||||
|
> this is a blockquote
|
||||||
|
|
||||||
|
par
|
||||||
|
***
|
||||||
|
par
|
||||||
|
|
||||||
|
This is some text
|
||||||
|
# Headline1
|
||||||
|
more text
|
||||||
19
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-basics.html
vendored
Normal file
19
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-basics.html
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<h1>GitHub Flavored Markdown</h1>
|
||||||
|
<h2>Multiple underscores in words</h2>
|
||||||
|
<p>do_this_and_do_that_and_another_thing</p>
|
||||||
|
<h2>URL autolinking</h2>
|
||||||
|
<p><a href="http://example.com">http://example.com</a></p>
|
||||||
|
<h2>Strikethrough</h2>
|
||||||
|
<p><del>Mistaken text.</del></p>
|
||||||
|
<h2>Fenced code blocks</h2>
|
||||||
|
<pre><code>function test() {
|
||||||
|
console.log("notice the blank line before this function?");
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h2>Syntax highlighting</h2>
|
||||||
|
<pre><code class="language-ruby">require 'redcarpet'
|
||||||
|
markdown = Redcarpet.new("Hello World!")
|
||||||
|
puts markdown.to_html
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>this is also code
|
||||||
|
</code></pre>
|
||||||
40
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-basics.md
vendored
Normal file
40
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-basics.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
GitHub Flavored Markdown
|
||||||
|
========================
|
||||||
|
|
||||||
|
Multiple underscores in words
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
do_this_and_do_that_and_another_thing
|
||||||
|
|
||||||
|
URL autolinking
|
||||||
|
---------------
|
||||||
|
|
||||||
|
http://example.com
|
||||||
|
|
||||||
|
Strikethrough
|
||||||
|
-------------
|
||||||
|
|
||||||
|
~~Mistaken text.~~
|
||||||
|
|
||||||
|
Fenced code blocks
|
||||||
|
------------------
|
||||||
|
|
||||||
|
```
|
||||||
|
function test() {
|
||||||
|
console.log("notice the blank line before this function?");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Syntax highlighting
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require 'redcarpet'
|
||||||
|
markdown = Redcarpet.new("Hello World!")
|
||||||
|
puts markdown.to_html
|
||||||
|
```
|
||||||
|
|
||||||
|
~~~
|
||||||
|
this is also code
|
||||||
|
~~~
|
||||||
|
|
||||||
12
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-code-in-numbered-list.html
vendored
Normal file
12
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-code-in-numbered-list.html
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<ol>
|
||||||
|
<li>Item one.</li>
|
||||||
|
<li><p>Item two with some code:</p>
|
||||||
|
<pre><code>code one
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
<li><p>Item three with code:</p>
|
||||||
|
<pre><code>code two
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>Paragraph.</p>
|
||||||
14
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-code-in-numbered-list.md
vendored
Normal file
14
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-code-in-numbered-list.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
1. Item one.
|
||||||
|
2. Item two with some code:
|
||||||
|
|
||||||
|
```
|
||||||
|
code one
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Item three with code:
|
||||||
|
|
||||||
|
```
|
||||||
|
code two
|
||||||
|
```
|
||||||
|
|
||||||
|
Paragraph.
|
||||||
117
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-sample.html
vendored
Normal file
117
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-sample.html
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<h1>GitHub Flavored Markdown</h1>
|
||||||
|
<p><em>View the <a href="http://github.github.com/github-flavored-markdown/sample_content.html">source of this content</a>.</em></p>
|
||||||
|
<p>Let's get the whole "linebreak" thing out of the way. The next paragraph contains two phrases separated by a single newline character:</p>
|
||||||
|
<p>Roses are red
|
||||||
|
Violets are blue</p>
|
||||||
|
<p>The next paragraph has the same phrases, but now they are separated by two spaces and a newline character:</p>
|
||||||
|
<p>Roses are red<br />
|
||||||
|
Violets are blue</p>
|
||||||
|
<p>Oh, and one thing I cannot stand is the mangling of words with multiple underscores in them like perform_complicated_task or do_this_and_do_that_and_another_thing.</p>
|
||||||
|
<h2>A bit of the GitHub spice</h2>
|
||||||
|
<p>In addition to the changes in the previous section, certain references are auto-linked:</p>
|
||||||
|
<ul>
|
||||||
|
<li>SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2</li>
|
||||||
|
<li>User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2</li>
|
||||||
|
<li>User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2</li>
|
||||||
|
<li>#Num: #1</li>
|
||||||
|
<li>User/#Num: mojombo#1</li>
|
||||||
|
<li>User/Project#Num: mojombo/god#1</li>
|
||||||
|
</ul>
|
||||||
|
<p>These are dangerous goodies though, and we need to make sure email addresses don't get mangled:</p>
|
||||||
|
<p>My email addy is tom@github.com.</p>
|
||||||
|
<h2>Math is hard, let's go shopping</h2>
|
||||||
|
<p>In first grade I learned that 5 > 3 and 2 < 7. Maybe some arrows. 1 -> 2 -> 3. 9 <- 8 <- 7.</p>
|
||||||
|
<p>Triangles man! a^2 + b^2 = c^2</p>
|
||||||
|
<h2>We all like making lists</h2>
|
||||||
|
<p>The above header should be an H2 tag. Now, for a list of fruits:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Red Apples</li>
|
||||||
|
<li>Purple Grapes</li>
|
||||||
|
<li>Green Kiwifruits</li>
|
||||||
|
</ul>
|
||||||
|
<p>Let's get crazy:</p>
|
||||||
|
<ol>
|
||||||
|
<li><p>This is a list item with two paragraphs. Lorem ipsum dolor
|
||||||
|
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
|
||||||
|
mi posuere lectus.</p>
|
||||||
|
<p>Vestibulum enim wisi, viverra nec, fringilla in, laoreet
|
||||||
|
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
|
||||||
|
sit amet velit.</p>
|
||||||
|
</li>
|
||||||
|
<li><p>Suspendisse id sem consectetuer libero luctus adipiscing.</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>What about some code <strong>in</strong> a list? That's insane, right?</p>
|
||||||
|
<ol>
|
||||||
|
<li><p>In Ruby you can map like this:</p>
|
||||||
|
<pre><code> ['a', 'b'].map { |x| x.uppercase }
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
<li><p>In Rails, you can do a shortcut:</p>
|
||||||
|
<pre><code> ['a', 'b'].map(&:uppercase)
|
||||||
|
</code></pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>Some people seem to like definition lists</p>
|
||||||
|
<dl>
|
||||||
|
<dt>Lower cost</dt>
|
||||||
|
<dd>The new version of this product costs significantly less than the previous one!</dd>
|
||||||
|
<dt>Easier to use</dt>
|
||||||
|
<dd>We've changed the product so that it's much easier to use!</dd>
|
||||||
|
</dl>
|
||||||
|
<h2>I am a robot</h2>
|
||||||
|
<p>Maybe you want to print <code>robot</code> to the console 1000 times. Why not?</p>
|
||||||
|
<pre><code>def robot_invasion
|
||||||
|
puts("robot " * 1000)
|
||||||
|
end
|
||||||
|
</code></pre>
|
||||||
|
<p>You see, that was formatted as code because it's been indented by four spaces.</p>
|
||||||
|
<p>How about we throw some angle braces and ampersands in there?</p>
|
||||||
|
<pre><code><div class="footer">
|
||||||
|
&copy; 2004 Foo Corporation
|
||||||
|
</div>
|
||||||
|
</code></pre>
|
||||||
|
<h2>Set in stone</h2>
|
||||||
|
<p>Preformatted blocks are useful for ASCII art:</p>
|
||||||
|
<pre>
|
||||||
|
,-.
|
||||||
|
, ,-. ,-.
|
||||||
|
/ \ ( )-( )
|
||||||
|
\ | ,.>-( )-<
|
||||||
|
\|,' ( )-( )
|
||||||
|
Y ___`-' `-'
|
||||||
|
|/__/ `-'
|
||||||
|
|
|
||||||
|
|
|
||||||
|
| -hrr-
|
||||||
|
___|_____________
|
||||||
|
</pre>
|
||||||
|
<h2>Playing the blame game</h2>
|
||||||
|
<p>If you need to blame someone, the best way to do so is by quoting them:</p>
|
||||||
|
<blockquote><p>I, at any rate, am convinced that He does not throw dice.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Or perhaps someone a little less eloquent:</p>
|
||||||
|
<blockquote><p>I wish you'd have given me this written question ahead of time so I
|
||||||
|
could plan for it... I'm sure something will pop into my head here in
|
||||||
|
the midst of this press conference, with all the pressure of trying to
|
||||||
|
come up with answer, but it hadn't yet...</p>
|
||||||
|
<p>I don't want to sound like
|
||||||
|
I have made no mistakes. I'm confident I have. I just haven't - you
|
||||||
|
just put me under the spot here, and maybe I'm not as quick on my feet
|
||||||
|
as I should be in coming up with one.</p>
|
||||||
|
</blockquote>
|
||||||
|
<h2>Table for two</h2>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th><th>Name</th><th>Rank</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>1</td><td>Tom Preston-Werner</td><td>Awesome</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>2</td><td>Albert Einstein</td><td>Nearly as awesome</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2>Crazy linking action</h2>
|
||||||
|
<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from
|
||||||
|
<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
|
||||||
159
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-sample.md
vendored
Normal file
159
core/lib/composer/vendor/cebe/markdown/tests/github-data/github-sample.md
vendored
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
GitHub Flavored Markdown
|
||||||
|
================================
|
||||||
|
|
||||||
|
*View the [source of this content](http://github.github.com/github-flavored-markdown/sample_content.html).*
|
||||||
|
|
||||||
|
Let's get the whole "linebreak" thing out of the way. The next paragraph contains two phrases separated by a single newline character:
|
||||||
|
|
||||||
|
Roses are red
|
||||||
|
Violets are blue
|
||||||
|
|
||||||
|
The next paragraph has the same phrases, but now they are separated by two spaces and a newline character:
|
||||||
|
|
||||||
|
Roses are red
|
||||||
|
Violets are blue
|
||||||
|
|
||||||
|
Oh, and one thing I cannot stand is the mangling of words with multiple underscores in them like perform_complicated_task or do_this_and_do_that_and_another_thing.
|
||||||
|
|
||||||
|
A bit of the GitHub spice
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
In addition to the changes in the previous section, certain references are auto-linked:
|
||||||
|
|
||||||
|
* SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||||
|
* User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||||
|
* User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||||
|
* \#Num: #1
|
||||||
|
* User/#Num: mojombo#1
|
||||||
|
* User/Project#Num: mojombo/god#1
|
||||||
|
|
||||||
|
These are dangerous goodies though, and we need to make sure email addresses don't get mangled:
|
||||||
|
|
||||||
|
My email addy is tom@github.com.
|
||||||
|
|
||||||
|
Math is hard, let's go shopping
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
In first grade I learned that 5 > 3 and 2 < 7. Maybe some arrows. 1 -> 2 -> 3. 9 <- 8 <- 7.
|
||||||
|
|
||||||
|
Triangles man! a^2 + b^2 = c^2
|
||||||
|
|
||||||
|
We all like making lists
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The above header should be an H2 tag. Now, for a list of fruits:
|
||||||
|
|
||||||
|
* Red Apples
|
||||||
|
* Purple Grapes
|
||||||
|
* Green Kiwifruits
|
||||||
|
|
||||||
|
Let's get crazy:
|
||||||
|
|
||||||
|
1. This is a list item with two paragraphs. Lorem ipsum dolor
|
||||||
|
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
|
||||||
|
mi posuere lectus.
|
||||||
|
|
||||||
|
Vestibulum enim wisi, viverra nec, fringilla in, laoreet
|
||||||
|
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
|
||||||
|
sit amet velit.
|
||||||
|
|
||||||
|
2. Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||||
|
|
||||||
|
What about some code **in** a list? That's insane, right?
|
||||||
|
|
||||||
|
1. In Ruby you can map like this:
|
||||||
|
|
||||||
|
['a', 'b'].map { |x| x.uppercase }
|
||||||
|
|
||||||
|
2. In Rails, you can do a shortcut:
|
||||||
|
|
||||||
|
['a', 'b'].map(&:uppercase)
|
||||||
|
|
||||||
|
Some people seem to like definition lists
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>Lower cost</dt>
|
||||||
|
<dd>The new version of this product costs significantly less than the previous one!</dd>
|
||||||
|
<dt>Easier to use</dt>
|
||||||
|
<dd>We've changed the product so that it's much easier to use!</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
I am a robot
|
||||||
|
------------
|
||||||
|
|
||||||
|
Maybe you want to print `robot` to the console 1000 times. Why not?
|
||||||
|
|
||||||
|
def robot_invasion
|
||||||
|
puts("robot " * 1000)
|
||||||
|
end
|
||||||
|
|
||||||
|
You see, that was formatted as code because it's been indented by four spaces.
|
||||||
|
|
||||||
|
How about we throw some angle braces and ampersands in there?
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
© 2004 Foo Corporation
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Set in stone
|
||||||
|
------------
|
||||||
|
|
||||||
|
Preformatted blocks are useful for ASCII art:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
,-.
|
||||||
|
, ,-. ,-.
|
||||||
|
/ \ ( )-( )
|
||||||
|
\ | ,.>-( )-<
|
||||||
|
\|,' ( )-( )
|
||||||
|
Y ___`-' `-'
|
||||||
|
|/__/ `-'
|
||||||
|
|
|
||||||
|
|
|
||||||
|
| -hrr-
|
||||||
|
___|_____________
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Playing the blame game
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
If you need to blame someone, the best way to do so is by quoting them:
|
||||||
|
|
||||||
|
> I, at any rate, am convinced that He does not throw dice.
|
||||||
|
|
||||||
|
Or perhaps someone a little less eloquent:
|
||||||
|
|
||||||
|
> I wish you'd have given me this written question ahead of time so I
|
||||||
|
> could plan for it... I'm sure something will pop into my head here in
|
||||||
|
> the midst of this press conference, with all the pressure of trying to
|
||||||
|
> come up with answer, but it hadn't yet...
|
||||||
|
>
|
||||||
|
> I don't want to sound like
|
||||||
|
> I have made no mistakes. I'm confident I have. I just haven't - you
|
||||||
|
> just put me under the spot here, and maybe I'm not as quick on my feet
|
||||||
|
> as I should be in coming up with one.
|
||||||
|
|
||||||
|
Table for two
|
||||||
|
-------------
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th><th>Name</th><th>Rank</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>1</td><td>Tom Preston-Werner</td><td>Awesome</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>2</td><td>Albert Einstein</td><td>Nearly as awesome</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
Crazy linking action
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
I get 10 times more traffic from [Google] [1] than from
|
||||||
|
[Yahoo] [2] or [MSN] [3].
|
||||||
|
|
||||||
|
[1]: http://google.com/ "Google"
|
||||||
|
[2]: http://search.yahoo.com/ "Yahoo Search"
|
||||||
|
[3]: http://search.msn.com/ "MSN Search"
|
||||||
5
core/lib/composer/vendor/cebe/markdown/tests/github-data/issue-33.html
vendored
Normal file
5
core/lib/composer/vendor/cebe/markdown/tests/github-data/issue-33.html
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<pre><code>hey, check [this].
|
||||||
|
|
||||||
|
[this]: https://github.com/cebe/markdown
|
||||||
|
</code></pre>
|
||||||
|
<p>is a vaild reference.</p>
|
||||||
6
core/lib/composer/vendor/cebe/markdown/tests/github-data/issue-33.md
vendored
Normal file
6
core/lib/composer/vendor/cebe/markdown/tests/github-data/issue-33.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
```
|
||||||
|
hey, check [this].
|
||||||
|
|
||||||
|
[this]: https://github.com/cebe/markdown
|
||||||
|
```
|
||||||
|
is a vaild reference.
|
||||||
21
core/lib/composer/vendor/cebe/markdown/tests/github-data/issue-38.html
vendored
Normal file
21
core/lib/composer/vendor/cebe/markdown/tests/github-data/issue-38.html
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<blockquote><p>some text
|
||||||
|
`<code>`
|
||||||
|
// some code
|
||||||
|
\</code>``</p>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><p>some text</p>
|
||||||
|
<pre><code>// some code
|
||||||
|
</code></pre>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><p>some text</p>
|
||||||
|
<pre><code>// some code
|
||||||
|
</code></pre>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><p>some text</p>
|
||||||
|
<pre><code>// some code
|
||||||
|
</code></pre>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote><p>some text</p>
|
||||||
|
</blockquote>
|
||||||
|
<pre><code>// some code
|
||||||
|
</code></pre>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user