Version Notes
https://github.com/SchumacherFM/Magento-Markdown
Download this release
Release Info
| Developer | Cyrill Schumacher |
| Extension | markdown |
| Version | 1.4.0 |
| Comparing to | |
| See all releases | |
Code changes from version 1.1.0 to 1.4.0
- app/code/community/SchumacherFM/Markdown/Helper/Data.php +58 -10
- app/code/community/SchumacherFM/Markdown/Model/Editor/Config.php +13 -15
- app/code/community/SchumacherFM/Markdown/Model/Markdown/Abstract.php +195 -0
- app/code/community/SchumacherFM/Markdown/Model/Markdown/Interface.php +21 -0
- app/code/community/SchumacherFM/Markdown/Model/Markdown/Observer.php +144 -0
- app/code/community/SchumacherFM/Markdown/Model/Markdown/Render.php +1 -213
- app/code/community/SchumacherFM/Markdown/Model/Michelf/Markdown.php +1 -1
- app/code/community/SchumacherFM/Markdown/Model/Observer/AdminhtmlBlock.php +91 -16
- app/code/community/SchumacherFM/Markdown/controllers/Adminhtml/MarkdownController.php +37 -0
- app/code/community/SchumacherFM/Markdown/etc/adminhtml.xml +1 -1
- app/code/community/SchumacherFM/Markdown/etc/config.xml +26 -4
- app/code/community/SchumacherFM/Markdown/etc/system.xml +23 -2
- app/design/adminhtml/default/default/layout/markdown.xml +7 -1
- js/mage/adminhtml/markdown.js +120 -53
- js/mage/adminhtml/marked.js +41 -27
- package.xml +10 -8
app/code/community/SchumacherFM/Markdown/Helper/Data.php
CHANGED
|
@@ -7,6 +7,8 @@
|
|
| 7 |
*/
|
| 8 |
class SchumacherFM_Markdown_Helper_Data extends Mage_Core_Helper_Abstract
|
| 9 |
{
|
|
|
|
|
|
|
| 10 |
|
| 11 |
/**
|
| 12 |
* easy access method for rendering markdown in phtml files
|
|
@@ -14,25 +16,26 @@ class SchumacherFM_Markdown_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 14 |
* echo Mage::helper('markdown')->render($_product->getDescription())
|
| 15 |
*
|
| 16 |
* @param string $text
|
| 17 |
-
* @param array
|
| 18 |
*
|
| 19 |
* @return string
|
| 20 |
*/
|
| 21 |
-
public function render($text,array $options = null)
|
| 22 |
{
|
| 23 |
return Mage::getSingleton('markdown/markdown_render')
|
| 24 |
->setOptions($options)
|
| 25 |
-
->renderMarkdown($text
|
| 26 |
}
|
| 27 |
|
| 28 |
/**
|
| 29 |
-
* @
|
| 30 |
*
|
| 31 |
-
* @return
|
| 32 |
*/
|
| 33 |
-
public function getDetectionTag()
|
| 34 |
{
|
| 35 |
-
|
|
|
|
| 36 |
}
|
| 37 |
|
| 38 |
/**
|
|
@@ -48,13 +51,58 @@ class SchumacherFM_Markdown_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 48 |
}
|
| 49 |
|
| 50 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
* @todo if backend check for current selected store view / website
|
| 52 |
* check if md extra is enabled ... per store view
|
| 53 |
*
|
| 54 |
-
* @return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
*/
|
| 56 |
-
public function
|
| 57 |
{
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
}
|
| 60 |
}
|
| 7 |
*/
|
| 8 |
class SchumacherFM_Markdown_Helper_Data extends Mage_Core_Helper_Abstract
|
| 9 |
{
|
| 10 |
+
const URL_MD_SYNTAX = 'http://daringfireball.net/projects/markdown/syntax';
|
| 11 |
+
const URL_MD_EXTRA_SYNTAX = 'http://michelf.ca/projects/php-markdown/extra/';
|
| 12 |
|
| 13 |
/**
|
| 14 |
* easy access method for rendering markdown in phtml files
|
| 16 |
* echo Mage::helper('markdown')->render($_product->getDescription())
|
| 17 |
*
|
| 18 |
* @param string $text
|
| 19 |
+
* @param array $options
|
| 20 |
*
|
| 21 |
* @return string
|
| 22 |
*/
|
| 23 |
+
public function render($text, array $options = null)
|
| 24 |
{
|
| 25 |
return Mage::getSingleton('markdown/markdown_render')
|
| 26 |
->setOptions($options)
|
| 27 |
+
->renderMarkdown($text);
|
| 28 |
}
|
| 29 |
|
| 30 |
/**
|
| 31 |
+
* @param bool $encoded
|
| 32 |
*
|
| 33 |
+
* @return mixed|string
|
| 34 |
*/
|
| 35 |
+
public function getDetectionTag($encoded = FALSE)
|
| 36 |
{
|
| 37 |
+
$tag = Mage::getStoreConfig('schumacherfm/markdown/detection_tag');
|
| 38 |
+
return $encoded ? rawurlencode($tag) : $tag;
|
| 39 |
}
|
| 40 |
|
| 41 |
/**
|
| 51 |
}
|
| 52 |
|
| 53 |
/**
|
| 54 |
+
* @param string $type enum email|page|block ... last two not supported, maybe later.
|
| 55 |
+
*
|
| 56 |
+
* @return bool
|
| 57 |
+
*/
|
| 58 |
+
public function isMarkdownExtra($type = null)
|
| 59 |
+
{
|
| 60 |
+
return (boolean)Mage::getStoreConfig('schumacherfm/markdown/md_extra' . (!empty($type) ? '_' . $type : ''));
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
/**
|
| 64 |
+
* loads CSS files and minifies it
|
| 65 |
+
*
|
| 66 |
* @todo if backend check for current selected store view / website
|
| 67 |
* check if md extra is enabled ... per store view
|
| 68 |
*
|
| 69 |
+
* @return string
|
| 70 |
+
*/
|
| 71 |
+
public function getTransactionalEmailCSS()
|
| 72 |
+
{
|
| 73 |
+
$file = Mage::getStoreConfig('schumacherfm/markdown/te_md_css');
|
| 74 |
+
if (empty($file)) {
|
| 75 |
+
return '';
|
| 76 |
+
}
|
| 77 |
+
$content = trim(implode('', @file(Mage::getBaseDir() . DS . $file)));
|
| 78 |
+
if (empty($content)) {
|
| 79 |
+
Mage::log('Markdown CSS file [' . $file . '] is empty!');
|
| 80 |
+
}
|
| 81 |
+
$content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content); // comments
|
| 82 |
+
$content = preg_replace('~\s+~', ' ', $content); // all whitespaces
|
| 83 |
+
$content = preg_replace('~\s*(:|\{|\}|,|;)\s*~', '\\1', $content); // all other whitespaces
|
| 84 |
+
return $content;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
/**
|
| 88 |
+
* @return string
|
| 89 |
+
*/
|
| 90 |
+
public function getAdminRenderUrl()
|
| 91 |
+
{
|
| 92 |
+
return Mage::helper("adminhtml")->getUrl('*/markdown/render');
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
/**
|
| 96 |
+
* @param string $htmlId
|
| 97 |
+
*
|
| 98 |
+
* @return string
|
| 99 |
*/
|
| 100 |
+
public function getRenderMarkdownJs($htmlId)
|
| 101 |
{
|
| 102 |
+
$args = array('\'' . $htmlId . '\'', '\'' . Mage::helper('markdown')->getDetectionTag(TRUE) . '\'');
|
| 103 |
+
if ($this->isMarkdownExtra()) {
|
| 104 |
+
$args[] = '\'' . $this->getAdminRenderUrl() . '\'';
|
| 105 |
+
}
|
| 106 |
+
return 'renderMarkdown(' . implode(',', $args) . ');';
|
| 107 |
}
|
| 108 |
}
|
app/code/community/SchumacherFM/Markdown/Model/Editor/Config.php
CHANGED
|
@@ -17,26 +17,24 @@ class SchumacherFM_Markdown_Model_Editor_Config
|
|
| 17 |
public function getWysiwygPluginSettings($config)
|
| 18 |
{
|
| 19 |
$variableConfig = array();
|
| 20 |
-
$
|
| 21 |
'search' => array('html_id'),
|
| 22 |
-
'subject' => '
|
| 23 |
);
|
| 24 |
-
$
|
| 25 |
'search' => array('html_id'),
|
| 26 |
-
'subject' => '
|
| 27 |
);
|
| 28 |
$variableWysiwygPlugin = array(
|
| 29 |
array(
|
| 30 |
'name' => 'markdownToggle',
|
| 31 |
'src' => '',
|
| 32 |
'options' => array(
|
| 33 |
-
'title' => Mage::helper('markdown')->__('
|
| 34 |
'url' => '',
|
| 35 |
'onclick' => array(
|
| 36 |
'search' => array('html_id'),
|
| 37 |
-
'subject' => 'toggleMarkdown(\''.
|
| 38 |
-
rawurlencode(Mage::helper('markdown')->getDetectionTag())
|
| 39 |
-
.'\',\'{{html_id}}\');'
|
| 40 |
),
|
| 41 |
'class' => 'plugin'
|
| 42 |
)
|
|
@@ -45,19 +43,19 @@ class SchumacherFM_Markdown_Model_Editor_Config
|
|
| 45 |
'name' => 'markdown',
|
| 46 |
'src' => '',
|
| 47 |
'options' => array(
|
| 48 |
-
'title' => Mage::helper('markdown')->__('
|
| 49 |
'url' => '',
|
| 50 |
-
'onclick' => $
|
| 51 |
'class' => 'plugin'
|
| 52 |
)
|
| 53 |
),
|
| 54 |
array(
|
| 55 |
-
'name' => '
|
| 56 |
'src' => '',
|
| 57 |
'options' => array(
|
| 58 |
-
'title' => Mage::helper('markdown')->__('
|
| 59 |
'url' => '',
|
| 60 |
-
'onclick' => $
|
| 61 |
'class' => 'plugin'
|
| 62 |
)
|
| 63 |
),
|
|
@@ -68,11 +66,11 @@ class SchumacherFM_Markdown_Model_Editor_Config
|
|
| 68 |
'name' => 'markdownextrasyntax',
|
| 69 |
'src' => '',
|
| 70 |
'options' => array(
|
| 71 |
-
'title' => Mage::helper('markdown')->__('
|
| 72 |
'url' => '',
|
| 73 |
'onclick' => array(
|
| 74 |
'search' => array('html_id'),
|
| 75 |
-
'subject' => '
|
| 76 |
),
|
| 77 |
'class' => 'plugin'
|
| 78 |
)
|
| 17 |
public function getWysiwygPluginSettings($config)
|
| 18 |
{
|
| 19 |
$variableConfig = array();
|
| 20 |
+
$onclickPreview = array(
|
| 21 |
'search' => array('html_id'),
|
| 22 |
+
'subject' => Mage::helper('markdown')->getRenderMarkdownJs('{{html_id}}'),
|
| 23 |
);
|
| 24 |
+
$onclickSyntax = array(
|
| 25 |
'search' => array('html_id'),
|
| 26 |
+
'subject' => 'mdExternalUrl(\'' . SchumacherFM_Markdown_Helper_Data::URL_MD_SYNTAX . '\',\'{{html_id}}\');'
|
| 27 |
);
|
| 28 |
$variableWysiwygPlugin = array(
|
| 29 |
array(
|
| 30 |
'name' => 'markdownToggle',
|
| 31 |
'src' => '',
|
| 32 |
'options' => array(
|
| 33 |
+
'title' => Mage::helper('markdown')->__('[M↓] enable'),
|
| 34 |
'url' => '',
|
| 35 |
'onclick' => array(
|
| 36 |
'search' => array('html_id'),
|
| 37 |
+
'subject' => 'toggleMarkdown(\'' . Mage::helper('markdown')->getDetectionTag(TRUE) . '\',\'{{html_id}}\');'
|
|
|
|
|
|
|
| 38 |
),
|
| 39 |
'class' => 'plugin'
|
| 40 |
)
|
| 43 |
'name' => 'markdown',
|
| 44 |
'src' => '',
|
| 45 |
'options' => array(
|
| 46 |
+
'title' => Mage::helper('markdown')->__('[M↓] Preview'),
|
| 47 |
'url' => '',
|
| 48 |
+
'onclick' => $onclickPreview,
|
| 49 |
'class' => 'plugin'
|
| 50 |
)
|
| 51 |
),
|
| 52 |
array(
|
| 53 |
+
'name' => 'mdExternalUrl',
|
| 54 |
'src' => '',
|
| 55 |
'options' => array(
|
| 56 |
+
'title' => Mage::helper('markdown')->__('[M↓] Syntax'),
|
| 57 |
'url' => '',
|
| 58 |
+
'onclick' => $onclickSyntax,
|
| 59 |
'class' => 'plugin'
|
| 60 |
)
|
| 61 |
),
|
| 66 |
'name' => 'markdownextrasyntax',
|
| 67 |
'src' => '',
|
| 68 |
'options' => array(
|
| 69 |
+
'title' => Mage::helper('markdown')->__('[M↓] Extra Syntax'),
|
| 70 |
'url' => '',
|
| 71 |
'onclick' => array(
|
| 72 |
'search' => array('html_id'),
|
| 73 |
+
'subject' => 'mdExternalUrl(\'' . SchumacherFM_Markdown_Helper_Data::URL_MD_EXTRA_SYNTAX . '\',\'{{html_id}}\');'
|
| 74 |
),
|
| 75 |
'class' => 'plugin'
|
| 76 |
)
|
app/code/community/SchumacherFM/Markdown/Model/Markdown/Abstract.php
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
/**
|
| 3 |
+
* @category SchumacherFM_Markdown
|
| 4 |
+
* @package Model
|
| 5 |
+
* @author Cyrill at Schumacher dot fm / @SchumacherFM
|
| 6 |
+
* @copyright Copyright (c)
|
| 7 |
+
*/
|
| 8 |
+
abstract class SchumacherFM_Markdown_Model_Markdown_Abstract
|
| 9 |
+
{
|
| 10 |
+
protected $_tag = '';
|
| 11 |
+
protected $_isDisabled = FALSE;
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* @var string
|
| 15 |
+
*/
|
| 16 |
+
private $_currentRenderedText = '';
|
| 17 |
+
|
| 18 |
+
/**
|
| 19 |
+
* @var array
|
| 20 |
+
*/
|
| 21 |
+
protected $_preserveContainer = array();
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* @var SchumacherFM_Markdown_Model_Michelf_Markdown
|
| 25 |
+
*/
|
| 26 |
+
protected $_renderer = null;
|
| 27 |
+
|
| 28 |
+
protected $_options = array(
|
| 29 |
+
'force' => FALSE,
|
| 30 |
+
'protectMagento' => TRUE,
|
| 31 |
+
);
|
| 32 |
+
|
| 33 |
+
public function __construct()
|
| 34 |
+
{
|
| 35 |
+
/**
|
| 36 |
+
* due to some weired parsings ... every text field which should contain MD must start with this tag
|
| 37 |
+
*/
|
| 38 |
+
$this->_tag = Mage::helper('markdown')->getDetectionTag();
|
| 39 |
+
$this->_isDisabled = Mage::helper('markdown')->isDisabled();
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
/**
|
| 43 |
+
* @return SchumacherFM_Markdown_Model_Michelf_Markdown
|
| 44 |
+
*/
|
| 45 |
+
public final function getRenderer()
|
| 46 |
+
{
|
| 47 |
+
if ($this->_renderer !== null) {
|
| 48 |
+
return $this->_renderer;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
$_isExtra = $this->_getIsExtraRenderer();
|
| 52 |
+
$this->_renderer = Mage::getModel($this->_getRendererModelName($_isExtra));
|
| 53 |
+
return $this->_renderer;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
/**
|
| 57 |
+
* for overloading please use this method to enable or disable the extra renderer
|
| 58 |
+
*
|
| 59 |
+
* @return boolean
|
| 60 |
+
*/
|
| 61 |
+
protected function _getIsExtraRenderer()
|
| 62 |
+
{
|
| 63 |
+
return Mage::helper('markdown')->isMarkdownExtra();
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
/**
|
| 67 |
+
* for overloading and using of your own markdown renderer use this method
|
| 68 |
+
*
|
| 69 |
+
* @param bool $_isExtra
|
| 70 |
+
*
|
| 71 |
+
* @return string
|
| 72 |
+
*/
|
| 73 |
+
protected function _getRendererModelName($_isExtra = FALSE)
|
| 74 |
+
{
|
| 75 |
+
return 'markdown/michelf_markdown' . ($_isExtra === TRUE ? '_extra' : '');
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
/**
|
| 79 |
+
* @param array $options
|
| 80 |
+
*
|
| 81 |
+
* @return $this
|
| 82 |
+
*/
|
| 83 |
+
public function setOptions(array $options = null)
|
| 84 |
+
{
|
| 85 |
+
$this->_options = $options;
|
| 86 |
+
return $this;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* @param string $text
|
| 91 |
+
*
|
| 92 |
+
* @return string
|
| 93 |
+
*/
|
| 94 |
+
public function renderMarkdown($text)
|
| 95 |
+
{
|
| 96 |
+
return $this->_isDisabled
|
| 97 |
+
? $text
|
| 98 |
+
: $this->_renderMarkdown($text);
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
/**
|
| 102 |
+
* @param string $text
|
| 103 |
+
*
|
| 104 |
+
* @return string
|
| 105 |
+
*/
|
| 106 |
+
protected function _renderMarkdown($text)
|
| 107 |
+
{
|
| 108 |
+
$force = isset($this->_options['force']) && $this->_options['force'] === TRUE;
|
| 109 |
+
$protectMagento = isset($this->_options['protectMagento']) && $this->_options['protectMagento'] === TRUE;
|
| 110 |
+
$this->_currentRenderedText = $text; // @todo optimize
|
| 111 |
+
|
| 112 |
+
if (!$this->_isMarkdown() && $force === FALSE) {
|
| 113 |
+
return $this->_currentRenderedText;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
$this->_removeMarkdownTag();
|
| 117 |
+
if ($protectMagento === TRUE) {
|
| 118 |
+
$this->_preserveMagentoVariablesEncode();
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
$this->_currentRenderedText = $this->getRenderer()->defaultTransform($this->_currentRenderedText);
|
| 122 |
+
|
| 123 |
+
if ($protectMagento === TRUE) {
|
| 124 |
+
$this->_preserveMagentoVariablesDecode();
|
| 125 |
+
}
|
| 126 |
+
return $this->_currentRenderedText;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
/**
|
| 130 |
+
* removes the markdown detection tag
|
| 131 |
+
*
|
| 132 |
+
* @return $this
|
| 133 |
+
*/
|
| 134 |
+
protected function _removeMarkdownTag()
|
| 135 |
+
{
|
| 136 |
+
$this->_currentRenderedText = str_replace($this->_tag, '', $this->_currentRenderedText);
|
| 137 |
+
return $this;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
/**
|
| 141 |
+
* @return $this
|
| 142 |
+
*/
|
| 143 |
+
protected function _preserveMagentoVariablesEncode()
|
| 144 |
+
{
|
| 145 |
+
$matches = array();
|
| 146 |
+
preg_match_all('~(\{\{[a-z]+.+\}\})~ismU', $this->_currentRenderedText, $matches, PREG_SET_ORDER);
|
| 147 |
+
if (count($matches) > 0) {
|
| 148 |
+
foreach ($matches as $match) {
|
| 149 |
+
$key = md5($match[0]);
|
| 150 |
+
$this->_preserveContainer[$key] = $match[0];
|
| 151 |
+
}
|
| 152 |
+
$this->_currentRenderedText = str_replace(
|
| 153 |
+
$this->_preserveContainer, array_keys($this->_preserveContainer), $this->_currentRenderedText
|
| 154 |
+
);
|
| 155 |
+
}
|
| 156 |
+
return $this;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
/**
|
| 160 |
+
* @return $this
|
| 161 |
+
*/
|
| 162 |
+
protected function _preserveMagentoVariablesDecode()
|
| 163 |
+
{
|
| 164 |
+
if (count($this->_preserveContainer) === 0) {
|
| 165 |
+
return $this;
|
| 166 |
+
}
|
| 167 |
+
$this->_currentRenderedText = str_replace(
|
| 168 |
+
array_keys($this->_preserveContainer), $this->_preserveContainer, $this->_currentRenderedText
|
| 169 |
+
);
|
| 170 |
+
$this->_preserveContainer = array();
|
| 171 |
+
return $this;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
/**
|
| 175 |
+
* checks if text contains no html ... if so considered as markdown ... not a nice way...
|
| 176 |
+
*
|
| 177 |
+
* @return bool
|
| 178 |
+
*/
|
| 179 |
+
private function _isMarkdown()
|
| 180 |
+
{
|
| 181 |
+
$flag = !empty($this->_currentRenderedText);
|
| 182 |
+
return $flag === TRUE && strpos($this->_currentRenderedText, $this->_tag) !== FALSE;
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
/**
|
| 186 |
+
* @param string reference $text
|
| 187 |
+
*
|
| 188 |
+
* @return bool
|
| 189 |
+
*/
|
| 190 |
+
public function isMarkdown(&$text)
|
| 191 |
+
{
|
| 192 |
+
return strpos($text, $this->_tag) !== FALSE;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
}
|
app/code/community/SchumacherFM/Markdown/Model/Markdown/Interface.php
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Markdown renderer Interface
|
| 5 |
+
*
|
| 6 |
+
* @category SchumacherFM_Markdown
|
| 7 |
+
* @package Model
|
| 8 |
+
* @author Cyrill at Schumacher dot fm / @SchumacherFM
|
| 9 |
+
* @copyright Copyright (c)
|
| 10 |
+
*/
|
| 11 |
+
interface SchumacherFM_Markdown_Model_Markdown_Interface
|
| 12 |
+
{
|
| 13 |
+
/**
|
| 14 |
+
* transform markdown into html
|
| 15 |
+
* @param string $text
|
| 16 |
+
*
|
| 17 |
+
* @return string
|
| 18 |
+
*/
|
| 19 |
+
public static function defaultTransform($text);
|
| 20 |
+
|
| 21 |
+
}
|
app/code/community/SchumacherFM/Markdown/Model/Markdown/Observer.php
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
/**
|
| 3 |
+
* @category SchumacherFM_Markdown
|
| 4 |
+
* @package Model
|
| 5 |
+
* @author Cyrill at Schumacher dot fm / @SchumacherFM
|
| 6 |
+
* @copyright Copyright (c)
|
| 7 |
+
*/
|
| 8 |
+
class SchumacherFM_Markdown_Model_Markdown_Observer extends SchumacherFM_Markdown_Model_Markdown_Abstract
|
| 9 |
+
{
|
| 10 |
+
/**
|
| 11 |
+
* @var null
|
| 12 |
+
*/
|
| 13 |
+
protected $_currentObserverMethod = null;
|
| 14 |
+
|
| 15 |
+
/**
|
| 16 |
+
* @var array
|
| 17 |
+
*/
|
| 18 |
+
protected $_mdExtraUsage = array(
|
| 19 |
+
// observer method => config value
|
| 20 |
+
'renderEmailTemplate' => 'email',
|
| 21 |
+
);
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* @return null|bool null = use global
|
| 25 |
+
*/
|
| 26 |
+
protected function _isObserverMdExtraUsage()
|
| 27 |
+
{
|
| 28 |
+
$isset = isset($this->_mdExtraUsage[$this->_currentObserverMethod]);
|
| 29 |
+
if (!$isset) {
|
| 30 |
+
return null;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
return Mage::helper('markdown')->isMarkdownExtra($this->_mdExtraUsage[$this->_currentObserverMethod]);
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
/**
|
| 37 |
+
* @return bool
|
| 38 |
+
*/
|
| 39 |
+
protected function _getIsExtraRenderer()
|
| 40 |
+
{
|
| 41 |
+
$globalExtra = parent::_getIsExtraRenderer();
|
| 42 |
+
$_observerMdExtraUsage = $this->_isObserverMdExtraUsage();
|
| 43 |
+
if ($_observerMdExtraUsage === null) {
|
| 44 |
+
return $globalExtra;
|
| 45 |
+
}
|
| 46 |
+
return $_observerMdExtraUsage;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
/**
|
| 50 |
+
* @param Varien_Event_Observer $observer
|
| 51 |
+
*
|
| 52 |
+
* @return null
|
| 53 |
+
*/
|
| 54 |
+
public function renderEmailTemplate(Varien_Event_Observer $observer)
|
| 55 |
+
{
|
| 56 |
+
$this->_currentObserverMethod = __FUNCTION__;
|
| 57 |
+
if ($this->_isDisabled) {
|
| 58 |
+
return null;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
$object = $observer->getEvent()->getObject();
|
| 62 |
+
if (!$object instanceof Mage_Core_Model_Email_Template) {
|
| 63 |
+
return null;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
$template = $object->getData('template_text');
|
| 67 |
+
|
| 68 |
+
if ($this->isMarkdown($template)) {
|
| 69 |
+
$object->setData('template_text', $this->_renderMarkdown($template));
|
| 70 |
+
$css = Mage::helper('markdown')->getTransactionalEmailCSS();
|
| 71 |
+
$object->setData('template_styles', $css);
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
/**
|
| 76 |
+
* @param Varien_Event_Observer $observer
|
| 77 |
+
*
|
| 78 |
+
* @return null
|
| 79 |
+
*/
|
| 80 |
+
public function renderPage(Varien_Event_Observer $observer)
|
| 81 |
+
{
|
| 82 |
+
$this->_currentObserverMethod = __FUNCTION__;
|
| 83 |
+
if ($this->_isDisabled) {
|
| 84 |
+
return null;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
/** @var Mage_Cms_Model_Page $page */
|
| 88 |
+
$page = $observer->getEvent()->getPage();
|
| 89 |
+
if (!$page instanceof Mage_Cms_Model_Page) {
|
| 90 |
+
return null;
|
| 91 |
+
}
|
| 92 |
+
$content = $this->_renderMarkdown($page->getContent());
|
| 93 |
+
$page->setContent($content);
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
/**
|
| 97 |
+
* renders every block as markdown except those having the html tags of method _isMarkdown in it
|
| 98 |
+
*
|
| 99 |
+
* @param Varien_Event_Observer $observer
|
| 100 |
+
*
|
| 101 |
+
* @return null
|
| 102 |
+
*/
|
| 103 |
+
public function renderBlock(Varien_Event_Observer $observer)
|
| 104 |
+
{
|
| 105 |
+
$this->_currentObserverMethod = __FUNCTION__;
|
| 106 |
+
if ($this->_isDisabled) {
|
| 107 |
+
return null;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
/** @var Mage_Cms_Block_Block $page */
|
| 111 |
+
$block = $observer->getEvent()->getBlock();
|
| 112 |
+
|
| 113 |
+
if (!$this->_isAllowedBlock($block)) {
|
| 114 |
+
return null;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
/** @var Varien_Object $transport */
|
| 118 |
+
$transport = $observer->getEvent()->getTransport();
|
| 119 |
+
|
| 120 |
+
/**
|
| 121 |
+
* you can set on any block the property ->setData('is_markdown',true)
|
| 122 |
+
* then the block will get rendered as markdown even if it contains html
|
| 123 |
+
*/
|
| 124 |
+
$isMarkdown = (boolean)$block->getIsMarkdown();
|
| 125 |
+
$this->setOptions(array(
|
| 126 |
+
'force' => $isMarkdown,
|
| 127 |
+
'protectMagento' => TRUE,
|
| 128 |
+
));
|
| 129 |
+
$html = $transport->getHtml();
|
| 130 |
+
$transport->setHtml($this->_renderMarkdown($html));
|
| 131 |
+
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
/**
|
| 135 |
+
* @param Varien_Object $block
|
| 136 |
+
*
|
| 137 |
+
* @return bool
|
| 138 |
+
*/
|
| 139 |
+
protected function _isAllowedBlock(Varien_Object $block)
|
| 140 |
+
{
|
| 141 |
+
return $block instanceof Mage_Cms_Block_Block || $block instanceof Mage_Cms_Block_Widget_Block;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
}
|
app/code/community/SchumacherFM/Markdown/Model/Markdown/Render.php
CHANGED
|
@@ -5,219 +5,7 @@
|
|
| 5 |
* @author Cyrill at Schumacher dot fm / @SchumacherFM
|
| 6 |
* @copyright Copyright (c)
|
| 7 |
*/
|
| 8 |
-
class SchumacherFM_Markdown_Model_Markdown_Render
|
| 9 |
{
|
| 10 |
-
private $_tag = '';
|
| 11 |
-
private $_isDisabled = FALSE;
|
| 12 |
-
|
| 13 |
-
/**
|
| 14 |
-
* @var string
|
| 15 |
-
*/
|
| 16 |
-
private $_currentRenderedText = '';
|
| 17 |
-
|
| 18 |
-
private $_preserveContainer = array();
|
| 19 |
-
|
| 20 |
-
/**
|
| 21 |
-
* @var SchumacherFM_Markdown_Model_Michelf_Markdown
|
| 22 |
-
*/
|
| 23 |
-
private $_renderer = null;
|
| 24 |
-
|
| 25 |
-
protected $_options = array();
|
| 26 |
-
|
| 27 |
-
public function __construct()
|
| 28 |
-
{
|
| 29 |
-
/**
|
| 30 |
-
* due to some weired parsings ... every text field which should contain MD must start with this tag
|
| 31 |
-
*/
|
| 32 |
-
$this->_tag = Mage::helper('markdown')->getDetectionTag();
|
| 33 |
-
$this->_isDisabled = Mage::helper('markdown')->isDisabled();
|
| 34 |
-
|
| 35 |
-
$isExtra = Mage::helper('markdown')->isMarkdownExtra() ? '_extra' : '';
|
| 36 |
-
$this->_renderer = Mage::getModel('markdown/michelf_markdown' . $isExtra);
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
/**
|
| 40 |
-
* @return SchumacherFM_Markdown_Model_Michelf_Markdown
|
| 41 |
-
*/
|
| 42 |
-
public function getRenderer()
|
| 43 |
-
{
|
| 44 |
-
return $this->_renderer;
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
/**
|
| 48 |
-
* @param array $options
|
| 49 |
-
*
|
| 50 |
-
* @return $this
|
| 51 |
-
*/
|
| 52 |
-
public function setOptions(array $options = null)
|
| 53 |
-
{
|
| 54 |
-
$this->_options = $options;
|
| 55 |
-
return $this;
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
/**
|
| 59 |
-
* @param string $text
|
| 60 |
-
*
|
| 61 |
-
* @return string
|
| 62 |
-
*/
|
| 63 |
-
public function renderMarkdown($text)
|
| 64 |
-
{
|
| 65 |
-
return $this->_isDisabled
|
| 66 |
-
? $text
|
| 67 |
-
: $this->_renderMarkdown($text);
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
/**
|
| 71 |
-
* @param Varien_Event_Observer $observer
|
| 72 |
-
*
|
| 73 |
-
* @return $this
|
| 74 |
-
*/
|
| 75 |
-
public function renderPageObserver(Varien_Event_Observer $observer)
|
| 76 |
-
{
|
| 77 |
-
if ($this->_isDisabled) {
|
| 78 |
-
return null;
|
| 79 |
-
}
|
| 80 |
-
|
| 81 |
-
/** @var Mage_Cms_Model_Page $page */
|
| 82 |
-
$page = $observer->getEvent()->getPage();
|
| 83 |
-
|
| 84 |
-
if ($page instanceof Mage_Cms_Model_Page) {
|
| 85 |
-
$this->setOptions(array(
|
| 86 |
-
'force' => FALSE,
|
| 87 |
-
'protectMagento' => TRUE,
|
| 88 |
-
));
|
| 89 |
-
$content = $this->_renderMarkdown($page->getContent());
|
| 90 |
-
$page->setContent($content);
|
| 91 |
-
}
|
| 92 |
-
|
| 93 |
-
return $this;
|
| 94 |
-
}
|
| 95 |
-
|
| 96 |
-
/**
|
| 97 |
-
* renders every block as markdown except those having the html tags of method _isMarkdown in it
|
| 98 |
-
*
|
| 99 |
-
* @param Varien_Event_Observer $observer
|
| 100 |
-
*
|
| 101 |
-
* @return $this
|
| 102 |
-
*/
|
| 103 |
-
public function renderBlockObserver(Varien_Event_Observer $observer)
|
| 104 |
-
{
|
| 105 |
-
if ($this->_isDisabled) {
|
| 106 |
-
return null;
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
-
/** @var Mage_Cms_Model_Page $page */
|
| 110 |
-
$block = $observer->getEvent()->getBlock();
|
| 111 |
-
|
| 112 |
-
if ($this->_isAllowedBlock($block)) {
|
| 113 |
-
/** @var Varien_Object $transport */
|
| 114 |
-
$transport = $observer->getEvent()->getTransport();
|
| 115 |
-
|
| 116 |
-
/**
|
| 117 |
-
* you can set on any block the property ->setData('is_markdown',true)
|
| 118 |
-
* then the block will get rendered as markdown even if it contains html
|
| 119 |
-
*/
|
| 120 |
-
$isMarkdown = (boolean)$block->getIsMarkdown();
|
| 121 |
-
$this->setOptions(array(
|
| 122 |
-
'force' => $isMarkdown,
|
| 123 |
-
'protectMagento' => FALSE,
|
| 124 |
-
));
|
| 125 |
-
$html = $transport->getHtml();
|
| 126 |
-
$transport->setHtml($this->_renderMarkdown($html));
|
| 127 |
-
|
| 128 |
-
}
|
| 129 |
-
return $this;
|
| 130 |
-
}
|
| 131 |
-
|
| 132 |
-
/**
|
| 133 |
-
* @param string $text
|
| 134 |
-
*
|
| 135 |
-
* @return string
|
| 136 |
-
*/
|
| 137 |
-
protected function _renderMarkdown($text)
|
| 138 |
-
{
|
| 139 |
-
$force = isset($this->_options['force']) && $this->_options['force'] === TRUE;
|
| 140 |
-
$protectMagento = isset($this->_options['protectMagento']) && $this->_options['protectMagento'] === TRUE;
|
| 141 |
-
$this->_currentRenderedText = $text;
|
| 142 |
-
if (!$this->_isMarkdown() && $force === FALSE) {
|
| 143 |
-
return $this->_currentRenderedText;
|
| 144 |
-
}
|
| 145 |
-
|
| 146 |
-
$this->_removeMarkdownTag();
|
| 147 |
-
if ($protectMagento) {
|
| 148 |
-
$this->_preserveMagentoVariablesEncode();
|
| 149 |
-
}
|
| 150 |
-
$this->_currentRenderedText = $this->getRenderer()->defaultTransform($this->_currentRenderedText);
|
| 151 |
-
if ($protectMagento) {
|
| 152 |
-
$this->_preserveMagentoVariablesDecode();
|
| 153 |
-
}
|
| 154 |
-
return $this->_currentRenderedText;
|
| 155 |
-
}
|
| 156 |
-
|
| 157 |
-
/**
|
| 158 |
-
* removes the markdown detection tag
|
| 159 |
-
*
|
| 160 |
-
* @return $this
|
| 161 |
-
*/
|
| 162 |
-
protected function _removeMarkdownTag()
|
| 163 |
-
{
|
| 164 |
-
$this->_currentRenderedText = str_replace($this->_tag, '', $this->_currentRenderedText);
|
| 165 |
-
return $this;
|
| 166 |
-
}
|
| 167 |
-
|
| 168 |
-
/**
|
| 169 |
-
* @return $this
|
| 170 |
-
*/
|
| 171 |
-
protected function _preserveMagentoVariablesEncode()
|
| 172 |
-
{
|
| 173 |
-
$matches = array();
|
| 174 |
-
preg_match_all('~(\{\{[a-z]+.+\}\})~ismU', $this->_currentRenderedText, $matches, PREG_SET_ORDER);
|
| 175 |
-
if (count($matches) > 0) {
|
| 176 |
-
foreach ($matches as $match) {
|
| 177 |
-
$key = md5($match[0]);
|
| 178 |
-
$this->_preserveContainer[$key] = $match[0];
|
| 179 |
-
}
|
| 180 |
-
$this->_currentRenderedText = str_replace(
|
| 181 |
-
$this->_preserveContainer, array_keys($this->_preserveContainer), $this->_currentRenderedText
|
| 182 |
-
);
|
| 183 |
-
}
|
| 184 |
-
return $this;
|
| 185 |
-
}
|
| 186 |
-
|
| 187 |
-
/**
|
| 188 |
-
* @return $this
|
| 189 |
-
*/
|
| 190 |
-
protected function _preserveMagentoVariablesDecode()
|
| 191 |
-
{
|
| 192 |
-
if (count($this->_preserveContainer) === 0) {
|
| 193 |
-
return $this;
|
| 194 |
-
}
|
| 195 |
-
$this->_currentRenderedText = str_replace(
|
| 196 |
-
array_keys($this->_preserveContainer), $this->_preserveContainer, $this->_currentRenderedText
|
| 197 |
-
);
|
| 198 |
-
$this->_preserveContainer = array();
|
| 199 |
-
return $this;
|
| 200 |
-
}
|
| 201 |
-
|
| 202 |
-
/**
|
| 203 |
-
* checks if text contains no html ... if so considered as markdown ... not a nice way...
|
| 204 |
-
*
|
| 205 |
-
* @return bool
|
| 206 |
-
*/
|
| 207 |
-
protected function _isMarkdown()
|
| 208 |
-
{
|
| 209 |
-
$flag = !empty($this->_currentRenderedText);
|
| 210 |
-
return $flag === TRUE && strpos($this->_currentRenderedText, $this->_tag) !== FALSE;
|
| 211 |
-
}
|
| 212 |
-
|
| 213 |
-
/**
|
| 214 |
-
* @param Mage_Core_Block_Abstract $block
|
| 215 |
-
*
|
| 216 |
-
* @return bool
|
| 217 |
-
*/
|
| 218 |
-
protected function _isAllowedBlock($block)
|
| 219 |
-
{
|
| 220 |
-
return $block instanceof Mage_Core_Block_Abstract;
|
| 221 |
-
}
|
| 222 |
|
| 223 |
}
|
| 5 |
* @author Cyrill at Schumacher dot fm / @SchumacherFM
|
| 6 |
* @copyright Copyright (c)
|
| 7 |
*/
|
| 8 |
+
class SchumacherFM_Markdown_Model_Markdown_Render extends SchumacherFM_Markdown_Model_Markdown_Abstract
|
| 9 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
}
|
app/code/community/SchumacherFM/Markdown/Model/Michelf/Markdown.php
CHANGED
|
@@ -13,7 +13,7 @@
|
|
| 13 |
# Markdown Parser Class
|
| 14 |
#
|
| 15 |
|
| 16 |
-
class SchumacherFM_Markdown_Model_Michelf_Markdown
|
| 17 |
{
|
| 18 |
|
| 19 |
### Version ###
|
| 13 |
# Markdown Parser Class
|
| 14 |
#
|
| 15 |
|
| 16 |
+
class SchumacherFM_Markdown_Model_Michelf_Markdown implements SchumacherFM_Markdown_Model_Markdown_Interface
|
| 17 |
{
|
| 18 |
|
| 19 |
### Version ###
|
app/code/community/SchumacherFM/Markdown/Model/Observer/AdminhtmlBlock.php
CHANGED
|
@@ -11,6 +11,8 @@ class SchumacherFM_Markdown_Model_Observer_AdminhtmlBlock
|
|
| 11 |
* adminhtml_block_html_before
|
| 12 |
*
|
| 13 |
* @param Varien_Event_Observer $observer
|
|
|
|
|
|
|
| 14 |
*/
|
| 15 |
public function alterTextareaBlockTemplate(Varien_Event_Observer $observer)
|
| 16 |
{
|
|
@@ -21,12 +23,24 @@ class SchumacherFM_Markdown_Model_Observer_AdminhtmlBlock
|
|
| 21 |
/** @var $block Mage_Adminhtml_Block_Template */
|
| 22 |
$block = $observer->getEvent()->getBlock();
|
| 23 |
|
| 24 |
-
if ($block instanceof
|
| 25 |
-
/** @var $
|
|
|
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
/** @var Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg $element */
|
| 28 |
$element = $block->getElement();
|
| 29 |
-
if ($this->
|
| 30 |
$this->_getMarkdownButtons($element);
|
| 31 |
}
|
| 32 |
}
|
|
@@ -37,7 +51,19 @@ class SchumacherFM_Markdown_Model_Observer_AdminhtmlBlock
|
|
| 37 |
*
|
| 38 |
* @return bool
|
| 39 |
*/
|
| 40 |
-
protected function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
{
|
| 42 |
$isTextarea = $element instanceof Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg;
|
| 43 |
$isDescription = stristr($element->getName(), 'description') !== FALSE && stristr($element->getName(), 'meta') === FALSE;
|
|
@@ -46,30 +72,79 @@ class SchumacherFM_Markdown_Model_Observer_AdminhtmlBlock
|
|
| 46 |
|
| 47 |
/**
|
| 48 |
* @param Varien_Data_Form_Element_Abstract $element
|
|
|
|
| 49 |
*/
|
| 50 |
-
protected function _getMarkdownButtons(Varien_Data_Form_Element_Abstract $element)
|
| 51 |
{
|
| 52 |
-
$html
|
|
|
|
| 53 |
|
| 54 |
-
$html
|
| 55 |
->createBlock('adminhtml/widget_button', '', array(
|
| 56 |
-
'label' => Mage::helper('markdown')->__('
|
| 57 |
'type' => 'button',
|
| 58 |
'class' => 'btn-wysiwyg',
|
| 59 |
-
'onclick' => 'toggleMarkdown(\'' .
|
| 60 |
-
|
| 61 |
-
. '\',\'' . $element->getHtmlId() . '\');'
|
| 62 |
-
))->toHtml().' ';
|
| 63 |
|
| 64 |
-
$html
|
| 65 |
->createBlock('adminhtml/widget_button', '', array(
|
| 66 |
-
'label' => Mage::helper('
|
| 67 |
'type' => 'button',
|
| 68 |
'class' => 'btn-wysiwyg',
|
| 69 |
-
'onclick' =>
|
| 70 |
))->toHtml();
|
| 71 |
|
| 72 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
}
|
| 74 |
|
| 75 |
}
|
| 11 |
* adminhtml_block_html_before
|
| 12 |
*
|
| 13 |
* @param Varien_Event_Observer $observer
|
| 14 |
+
*
|
| 15 |
+
* @return null
|
| 16 |
*/
|
| 17 |
public function alterTextareaBlockTemplate(Varien_Event_Observer $observer)
|
| 18 |
{
|
| 23 |
/** @var $block Mage_Adminhtml_Block_Template */
|
| 24 |
$block = $observer->getEvent()->getBlock();
|
| 25 |
|
| 26 |
+
if ($block instanceof Mage_Adminhtml_Block_Widget_Form_Renderer_Fieldset_Element) {
|
| 27 |
+
/** @var Varien_Data_Form_Element_Abstract $element */
|
| 28 |
+
$element = $block->getElement();
|
| 29 |
|
| 30 |
+
if ($this->_isEmailTemplateElementAllowed($element)) {
|
| 31 |
+
$element->setData('after_element_html', ' ');
|
| 32 |
+
$this->_getMarkdownButtons($element, 'template_text');
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
if ($this->_isElementEditor($element)) {
|
| 36 |
+
$this->_addLivePreviewToEditor($element);
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
if ($block instanceof Mage_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_Element) {
|
| 41 |
/** @var Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg $element */
|
| 42 |
$element = $block->getElement();
|
| 43 |
+
if ($this->_isCatalogElementAllowed($element)) {
|
| 44 |
$this->_getMarkdownButtons($element);
|
| 45 |
}
|
| 46 |
}
|
| 51 |
*
|
| 52 |
* @return bool
|
| 53 |
*/
|
| 54 |
+
protected function _isEmailTemplateElementAllowed(Varien_Data_Form_Element_Abstract $element)
|
| 55 |
+
{
|
| 56 |
+
$trueOne = $element instanceof Varien_Data_Form_Element_Note;
|
| 57 |
+
$trueTwo = stristr($element->getHtmlId(), 'insert_variable') !== FALSE;
|
| 58 |
+
return $trueOne && $trueTwo;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
/**
|
| 62 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
| 63 |
+
*
|
| 64 |
+
* @return bool
|
| 65 |
+
*/
|
| 66 |
+
protected function _isCatalogElementAllowed(Varien_Data_Form_Element_Abstract $element)
|
| 67 |
{
|
| 68 |
$isTextarea = $element instanceof Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg;
|
| 69 |
$isDescription = stristr($element->getName(), 'description') !== FALSE && stristr($element->getName(), 'meta') === FALSE;
|
| 72 |
|
| 73 |
/**
|
| 74 |
* @param Varien_Data_Form_Element_Abstract $element
|
| 75 |
+
* @param string|null $htmlId
|
| 76 |
*/
|
| 77 |
+
protected function _getMarkdownButtons(Varien_Data_Form_Element_Abstract $element, $htmlId = null)
|
| 78 |
{
|
| 79 |
+
$html = array($element->getData('after_element_html'));
|
| 80 |
+
$htmlId = empty($htmlId) ? $element->getHtmlId() : $htmlId;
|
| 81 |
|
| 82 |
+
$html[] = Mage::getSingleton('core/layout')
|
| 83 |
->createBlock('adminhtml/widget_button', '', array(
|
| 84 |
+
'label' => Mage::helper('markdown')->__('[M↓] enable'),
|
| 85 |
'type' => 'button',
|
| 86 |
'class' => 'btn-wysiwyg',
|
| 87 |
+
'onclick' => 'toggleMarkdown(\'' . Mage::helper('markdown')->getDetectionTag(TRUE) . '\',\'' . $htmlId . '\');'
|
| 88 |
+
))->toHtml();
|
|
|
|
|
|
|
| 89 |
|
| 90 |
+
$html[] = Mage::getSingleton('core/layout')
|
| 91 |
->createBlock('adminhtml/widget_button', '', array(
|
| 92 |
+
'label' => Mage::helper('markdown')->__('[M↓] Preview'),
|
| 93 |
'type' => 'button',
|
| 94 |
'class' => 'btn-wysiwyg',
|
| 95 |
+
'onclick' => Mage::helper('markdown')->getRenderMarkdownJs($htmlId),
|
| 96 |
))->toHtml();
|
| 97 |
|
| 98 |
+
$html[] = Mage::getSingleton('core/layout')
|
| 99 |
+
->createBlock('adminhtml/widget_button', '', array(
|
| 100 |
+
'label' => Mage::helper('markdown')->__('[M↓] Syntax'),
|
| 101 |
+
'type' => 'button',
|
| 102 |
+
'class' => 'btn-wysiwyg',
|
| 103 |
+
'onclick' => 'mdExternalUrl(\'' . SchumacherFM_Markdown_Helper_Data::URL_MD_SYNTAX . '\');'
|
| 104 |
+
))->toHtml();
|
| 105 |
+
|
| 106 |
+
if (Mage::helper('markdown')->isMarkdownExtra()) {
|
| 107 |
+
|
| 108 |
+
$html[] = Mage::getSingleton('core/layout')
|
| 109 |
+
->createBlock('adminhtml/widget_button', '', array(
|
| 110 |
+
'label' => Mage::helper('markdown')->__('[M↓] Extra Syntax'),
|
| 111 |
+
'type' => 'button',
|
| 112 |
+
'class' => 'btn-wysiwyg',
|
| 113 |
+
'onclick' => 'mdExternalUrl(\'' . SchumacherFM_Markdown_Helper_Data::URL_MD_EXTRA_SYNTAX . '\');'
|
| 114 |
+
))->toHtml();
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
$element->setData('after_element_html', implode(' ', $html));
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
/**
|
| 121 |
+
* Live preview only available for non markdown extra mode.
|
| 122 |
+
* otherwise the ajax request and php markdown rendering would kill the users patience
|
| 123 |
+
*
|
| 124 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
| 125 |
+
*
|
| 126 |
+
* @return bool
|
| 127 |
+
*/
|
| 128 |
+
protected function _isElementEditor(Varien_Data_Form_Element_Abstract $element)
|
| 129 |
+
{
|
| 130 |
+
return !Mage::helper('markdown')->isMarkdownExtra() && $element instanceof Varien_Data_Form_Element_Editor;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
/**
|
| 134 |
+
* @param Varien_Data_Form_Element_Editor $element
|
| 135 |
+
*
|
| 136 |
+
* @return $this
|
| 137 |
+
*/
|
| 138 |
+
protected function _addLivePreviewToEditor(Varien_Data_Form_Element_Editor $element)
|
| 139 |
+
{
|
| 140 |
+
$previewHtml = '<div id="markdown_live_preview"
|
| 141 |
+
style="overflow:scroll; height:25em;"
|
| 142 |
+
data-mddetector="' . Mage::helper('markdown')->getDetectionTag(TRUE) . '"
|
| 143 |
+
data-elementid="' . $element->getHtmlId() . '" class="buttons-set"><div class="markdown">' .
|
| 144 |
+
Mage::helper('markdown')->__('[M↓] Live Preview enabled ...')
|
| 145 |
+
. '</div></div>';
|
| 146 |
+
$element->setData('after_element_html', $previewHtml);
|
| 147 |
+
return $this;
|
| 148 |
}
|
| 149 |
|
| 150 |
}
|
app/code/community/SchumacherFM/Markdown/controllers/Adminhtml/MarkdownController.php
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
/**
|
| 3 |
+
* @category SchumacherFM_Markdown
|
| 4 |
+
* @package Controller
|
| 5 |
+
* @author Cyrill at Schumacher dot fm / @SchumacherFM
|
| 6 |
+
* @copyright Copyright (c)
|
| 7 |
+
*/
|
| 8 |
+
class SchumacherFM_Markdown_Adminhtml_MarkdownController extends Mage_Adminhtml_Controller_Action
|
| 9 |
+
{
|
| 10 |
+
|
| 11 |
+
/**
|
| 12 |
+
* @return void
|
| 13 |
+
*/
|
| 14 |
+
public function renderAction()
|
| 15 |
+
{
|
| 16 |
+
$content = $this->getRequest()->getParam('content', null);
|
| 17 |
+
if (!$this->getRequest()->isPost() || empty($content)) {
|
| 18 |
+
return $this->_setReturn();
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
$md = Mage::helper('markdown')->render($content);
|
| 22 |
+
return $this->_setReturn($md);
|
| 23 |
+
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
/**
|
| 27 |
+
* @param string $string
|
| 28 |
+
*
|
| 29 |
+
* @return $this
|
| 30 |
+
*/
|
| 31 |
+
protected function _setReturn($string = '')
|
| 32 |
+
{
|
| 33 |
+
$this->getResponse()->setBody($string);
|
| 34 |
+
return $this;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
}
|
app/code/community/SchumacherFM/Markdown/etc/adminhtml.xml
CHANGED
|
@@ -27,4 +27,4 @@
|
|
| 27 |
</admin>
|
| 28 |
</resources>
|
| 29 |
</acl>
|
| 30 |
-
</config>
|
| 27 |
</admin>
|
| 28 |
</resources>
|
| 29 |
</acl>
|
| 30 |
+
</config>
|
app/code/community/SchumacherFM/Markdown/etc/config.xml
CHANGED
|
@@ -40,8 +40,8 @@
|
|
| 40 |
<observers>
|
| 41 |
<markdown_renderer>
|
| 42 |
<type>singleton</type>
|
| 43 |
-
<class>markdown/
|
| 44 |
-
<method>
|
| 45 |
</markdown_renderer>
|
| 46 |
</observers>
|
| 47 |
</cms_page_render>
|
|
@@ -50,14 +50,35 @@
|
|
| 50 |
<observers>
|
| 51 |
<markdown_renderer>
|
| 52 |
<type>singleton</type>
|
| 53 |
-
<class>markdown/
|
| 54 |
-
<method>
|
| 55 |
</markdown_renderer>
|
| 56 |
</observers>
|
| 57 |
</core_block_abstract_to_html_after>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
</events>
|
| 59 |
</frontend>
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
<adminhtml>
|
| 62 |
<layout>
|
| 63 |
<updates>
|
|
@@ -107,6 +128,7 @@
|
|
| 107 |
<markdown>
|
| 108 |
<enable>1</enable>
|
| 109 |
<md_extra>0</md_extra>
|
|
|
|
| 110 |
<detection_tag>!#markdown</detection_tag>
|
| 111 |
</markdown>
|
| 112 |
</schumacherfm>
|
| 40 |
<observers>
|
| 41 |
<markdown_renderer>
|
| 42 |
<type>singleton</type>
|
| 43 |
+
<class>markdown/markdown_observer</class>
|
| 44 |
+
<method>renderPage</method>
|
| 45 |
</markdown_renderer>
|
| 46 |
</observers>
|
| 47 |
</cms_page_render>
|
| 50 |
<observers>
|
| 51 |
<markdown_renderer>
|
| 52 |
<type>singleton</type>
|
| 53 |
+
<class>markdown/markdown_observer</class>
|
| 54 |
+
<method>renderBlock</method>
|
| 55 |
</markdown_renderer>
|
| 56 |
</observers>
|
| 57 |
</core_block_abstract_to_html_after>
|
| 58 |
+
|
| 59 |
+
<core_abstract_load_after>
|
| 60 |
+
<observers>
|
| 61 |
+
<markdown_core_email_template>
|
| 62 |
+
<class>markdown/markdown_observer</class>
|
| 63 |
+
<method>renderEmailTemplate</method>
|
| 64 |
+
</markdown_core_email_template>
|
| 65 |
+
</observers>
|
| 66 |
+
</core_abstract_load_after>
|
| 67 |
</events>
|
| 68 |
</frontend>
|
| 69 |
|
| 70 |
+
<admin>
|
| 71 |
+
<routers>
|
| 72 |
+
<adminhtml>
|
| 73 |
+
<args>
|
| 74 |
+
<modules>
|
| 75 |
+
<markdown before="Mage_Adminhtml">SchumacherFM_Markdown_Adminhtml</markdown>
|
| 76 |
+
</modules>
|
| 77 |
+
</args>
|
| 78 |
+
</adminhtml>
|
| 79 |
+
</routers>
|
| 80 |
+
</admin>
|
| 81 |
+
|
| 82 |
<adminhtml>
|
| 83 |
<layout>
|
| 84 |
<updates>
|
| 128 |
<markdown>
|
| 129 |
<enable>1</enable>
|
| 130 |
<md_extra>0</md_extra>
|
| 131 |
+
<md_extra_email>0</md_extra_email>
|
| 132 |
<detection_tag>!#markdown</detection_tag>
|
| 133 |
</markdown>
|
| 134 |
</schumacherfm>
|
app/code/community/SchumacherFM/Markdown/etc/system.xml
CHANGED
|
@@ -19,7 +19,7 @@
|
|
| 19 |
<show_in_store>1</show_in_store>
|
| 20 |
<groups>
|
| 21 |
<markdown translate="label">
|
| 22 |
-
<label>Markdown</label>
|
| 23 |
<frontend_type>text</frontend_type>
|
| 24 |
<sort_order>50</sort_order>
|
| 25 |
<show_in_default>1</show_in_default>
|
|
@@ -52,8 +52,29 @@
|
|
| 52 |
<show_in_website>1</show_in_website>
|
| 53 |
<show_in_store>1</show_in_store>
|
| 54 |
<comment>Every content field which contains markdown must have this tag included that it will be parsed.
|
| 55 |
-
This tag will of course be removed during parsing. If empty, every content is considered as markdown
|
|
|
|
|
|
|
| 56 |
</detection_tag>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
</fields>
|
| 58 |
</markdown>
|
| 59 |
</groups>
|
| 19 |
<show_in_store>1</show_in_store>
|
| 20 |
<groups>
|
| 21 |
<markdown translate="label">
|
| 22 |
+
<label>Markdown [M↓]</label>
|
| 23 |
<frontend_type>text</frontend_type>
|
| 24 |
<sort_order>50</sort_order>
|
| 25 |
<show_in_default>1</show_in_default>
|
| 52 |
<show_in_website>1</show_in_website>
|
| 53 |
<show_in_store>1</show_in_store>
|
| 54 |
<comment>Every content field which contains markdown must have this tag included that it will be parsed.
|
| 55 |
+
This tag will of course be removed during parsing. If empty, every content is considered as markdown.
|
| 56 |
+
Only transactional emails which have the detection tag somewhere integrated will be rendered with markdown.
|
| 57 |
+
</comment>
|
| 58 |
</detection_tag>
|
| 59 |
+
<md_extra_email translate="label">
|
| 60 |
+
<label>Transactional email: Use Markdown Extra</label>
|
| 61 |
+
<frontend_type>select</frontend_type>
|
| 62 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
| 63 |
+
<sort_order>140</sort_order>
|
| 64 |
+
<show_in_default>1</show_in_default>
|
| 65 |
+
<show_in_website>1</show_in_website>
|
| 66 |
+
<show_in_store>1</show_in_store>
|
| 67 |
+
</md_extra_email>
|
| 68 |
+
<te_md_css translate="label">
|
| 69 |
+
<label>Transactional email: Path to CSS file</label>
|
| 70 |
+
<frontend_type>text</frontend_type>
|
| 71 |
+
<sort_order>150</sort_order>
|
| 72 |
+
<show_in_default>1</show_in_default>
|
| 73 |
+
<show_in_website>1</show_in_website>
|
| 74 |
+
<show_in_store>1</show_in_store>
|
| 75 |
+
<comment><![CDATA[Relative path to the CSS to include in a transactional email. Mage::getBaseDir() is prefixed.
|
| 76 |
+
Will be included in the <style> tag in each email.]]></comment>
|
| 77 |
+
</te_md_css>
|
| 78 |
</fields>
|
| 79 |
</markdown>
|
| 80 |
</groups>
|
app/design/adminhtml/default/default/layout/markdown.xml
CHANGED
|
@@ -1,10 +1,16 @@
|
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<layout>
|
| 3 |
-
<
|
| 4 |
<reference name="head">
|
| 5 |
<action method="addJs"><script>mage/adminhtml/markdown.js</script></action>
|
| 6 |
<action method="addJs"><script>mage/adminhtml/marked.js</script></action>
|
| 7 |
<action method="addCss"><name>markdown.css</name></action>
|
| 8 |
</reference>
|
|
|
|
|
|
|
|
|
|
| 9 |
</editor>
|
|
|
|
|
|
|
|
|
|
| 10 |
</layout>
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<layout>
|
| 3 |
+
<MARKDOWN_HEADER>
|
| 4 |
<reference name="head">
|
| 5 |
<action method="addJs"><script>mage/adminhtml/markdown.js</script></action>
|
| 6 |
<action method="addJs"><script>mage/adminhtml/marked.js</script></action>
|
| 7 |
<action method="addCss"><name>markdown.css</name></action>
|
| 8 |
</reference>
|
| 9 |
+
</MARKDOWN_HEADER>
|
| 10 |
+
<editor>
|
| 11 |
+
<update handle="MARKDOWN_HEADER"/>
|
| 12 |
</editor>
|
| 13 |
+
<adminhtml_system_email_template_edit>
|
| 14 |
+
<update handle="MARKDOWN_HEADER"/>
|
| 15 |
+
</adminhtml_system_email_template_edit>
|
| 16 |
</layout>
|
js/mage/adminhtml/markdown.js
CHANGED
|
@@ -6,72 +6,139 @@
|
|
| 6 |
*/
|
| 7 |
;
|
| 8 |
(function () {
|
| 9 |
-
var
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
var TEXT_SUFFIX = '</div>';
|
| 14 |
-
|
| 15 |
-
var htmlId = '';
|
| 16 |
-
|
| 17 |
-
var showPreview = function (responseText) {
|
| 18 |
-
|
| 19 |
-
dialogWindow = Dialog.info(TEXT_PREFIX + responseText + TEXT_SUFFIX, {
|
| 20 |
-
draggable: true,
|
| 21 |
-
resizable: true,
|
| 22 |
-
closable: true,
|
| 23 |
-
className: "magento",
|
| 24 |
-
windowClassName: "popup-window",
|
| 25 |
-
title: 'Markdown Preview',
|
| 26 |
-
width: 800,
|
| 27 |
-
height: 480,
|
| 28 |
-
zIndex: 1000,
|
| 29 |
-
recenterAuto: false,
|
| 30 |
-
hideEffect: Element.hide,
|
| 31 |
-
showEffect: Element.show,
|
| 32 |
-
id: dialogWindowId,
|
| 33 |
-
onClose: closeDialogWindow.bind(this)
|
| 34 |
-
});
|
| 35 |
-
}
|
| 36 |
|
| 37 |
-
|
| 38 |
-
if (!window) {
|
| 39 |
-
window = dialogWindow;
|
| 40 |
-
}
|
| 41 |
-
if (window) {
|
| 42 |
-
window.close();
|
| 43 |
-
}
|
| 44 |
-
}
|
| 45 |
|
| 46 |
-
|
| 47 |
-
showPreview(marked($(htmlId).value));
|
| 48 |
-
}
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
-
|
| 63 |
-
detectionTag = unescape(detectionTag);
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
}
|
| 68 |
-
alert('Markdown enabled with tag: "' + detectionTag+'"');
|
| 69 |
}
|
| 70 |
|
| 71 |
this.renderMarkdown = renderMarkdown;
|
| 72 |
-
this.
|
| 73 |
this.toggleMarkdown = toggleMarkdown;
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
}).call(function () {
|
| 76 |
return this || (typeof window !== 'undefined' ? window : global);
|
| 77 |
}());
|
| 6 |
*/
|
| 7 |
;
|
| 8 |
(function () {
|
| 9 |
+
var dialogWindow,
|
| 10 |
+
dialogWindowId = 'markdown-preview',
|
| 11 |
+
TEXT_PREFIX = '<div class="markdown">',
|
| 12 |
+
TEXT_SUFFIX = '</div>',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
+
htmlId = '',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
+
showPreview = function (responseText) {
|
|
|
|
|
|
|
| 17 |
|
| 18 |
+
dialogWindow = Dialog.info(TEXT_PREFIX + responseText + TEXT_SUFFIX, {
|
| 19 |
+
draggable: true,
|
| 20 |
+
resizable: true,
|
| 21 |
+
closable: true,
|
| 22 |
+
className: "magento",
|
| 23 |
+
windowClassName: "popup-window",
|
| 24 |
+
title: 'Markdown Preview',
|
| 25 |
+
width: 800,
|
| 26 |
+
height: 480,
|
| 27 |
+
zIndex: 1000,
|
| 28 |
+
recenterAuto: false,
|
| 29 |
+
hideEffect: Element.hide,
|
| 30 |
+
showEffect: Element.show,
|
| 31 |
+
id: dialogWindowId,
|
| 32 |
+
onClose: closeDialogWindow.bind(this)
|
| 33 |
+
});
|
| 34 |
+
},
|
| 35 |
|
| 36 |
+
closeDialogWindow = function (window) {
|
| 37 |
+
if (!window) {
|
| 38 |
+
window = dialogWindow;
|
| 39 |
+
}
|
| 40 |
+
if (window) {
|
| 41 |
+
window.close();
|
| 42 |
+
}
|
| 43 |
+
},
|
| 44 |
|
| 45 |
+
_renderMarkdownJs = function (mdDetector) {
|
| 46 |
+
mdDetector = unescape(mdDetector);
|
| 47 |
+
showPreview(marked($(htmlId).value.replace(mdDetector, '')));
|
| 48 |
+
},
|
| 49 |
+
|
| 50 |
+
_renderMarkdownAjax = function (url) {
|
| 51 |
+
new Ajax.Request(url, {
|
| 52 |
+
method: 'post',
|
| 53 |
+
parameters: {"content": $(htmlId).value},
|
| 54 |
+
onComplete: function (data) {
|
| 55 |
+
showPreview((data && data.responseText) ? data.responseText : 'Ajax Error');
|
| 56 |
+
}
|
| 57 |
+
});
|
| 58 |
+
|
| 59 |
+
},
|
| 60 |
+
|
| 61 |
+
renderMarkdown = function (Idhtml, mdDetector, renderUrl) {
|
| 62 |
+
htmlId = Idhtml;
|
| 63 |
+
if (renderUrl && typeof renderUrl === 'string') {
|
| 64 |
+
_renderMarkdownAjax(renderUrl);
|
| 65 |
+
} else {
|
| 66 |
+
_renderMarkdownJs(mdDetector);
|
| 67 |
+
}
|
| 68 |
+
return;
|
| 69 |
|
| 70 |
+
},
|
|
|
|
| 71 |
|
| 72 |
+
mdExternalUrl = function (url, Idhtml) {
|
| 73 |
+
htmlId = Idhtml;
|
| 74 |
+
window.open(url);
|
| 75 |
+
},
|
| 76 |
+
|
| 77 |
+
toggleMarkdown = function (detectionTag, Idhtml) {
|
| 78 |
+
detectionTag = unescape(detectionTag);
|
| 79 |
+
|
| 80 |
+
if ($(Idhtml).value.indexOf(detectionTag) === -1) {
|
| 81 |
+
$(Idhtml).value = detectionTag + "\n" + $(Idhtml).value;
|
| 82 |
+
}
|
| 83 |
+
alert('Markdown enabled with tag: "' + detectionTag + '"');
|
| 84 |
+
},
|
| 85 |
+
|
| 86 |
+
_livePreview = function ($markdownLivePreview) {
|
| 87 |
+
var editorId = $markdownLivePreview.readAttribute('data-elementid'),
|
| 88 |
+
$editorId = $(editorId),
|
| 89 |
+
_mdHandling = new _mdHandler();
|
| 90 |
+
|
| 91 |
+
_mdHandling.setMdDetector($markdownLivePreview);
|
| 92 |
+
|
| 93 |
+
var _originalHeight = $markdownLivePreview.getStyle('height'), _clicked = false;
|
| 94 |
+
$markdownLivePreview.observe('click', function (e) {
|
| 95 |
+
var css = {height: ''};
|
| 96 |
+
if (_clicked) {
|
| 97 |
+
css['height'] = _originalHeight;
|
| 98 |
+
_clicked = false;
|
| 99 |
+
} else {
|
| 100 |
+
_clicked = true;
|
| 101 |
+
}
|
| 102 |
+
$markdownLivePreview.setStyle(css);
|
| 103 |
+
});
|
| 104 |
+
|
| 105 |
+
$editorId.observe('keyup', function (e) {
|
| 106 |
+
_mdHandling.text = e.target.value;
|
| 107 |
+
$markdownLivePreview.innerHTML = _mdHandling.hasMarkdown()
|
| 108 |
+
? _mdHandling.getRenderedMarkdown()
|
| 109 |
+
: 'Offline ...';
|
| 110 |
+
});
|
| 111 |
+
},
|
| 112 |
+
|
| 113 |
+
_mdHandler = function () {
|
| 114 |
+
this.text = '';
|
| 115 |
+
this._mdDetector = '';
|
| 116 |
+
};
|
| 117 |
+
|
| 118 |
+
_mdHandler.prototype = {
|
| 119 |
+
setMdDetector: function ($markdownLivePreview) {
|
| 120 |
+
this._mdDetector = unescape($markdownLivePreview.readAttribute('data-mddetector') || '~~~@#$#@!');
|
| 121 |
+
return this;
|
| 122 |
+
},
|
| 123 |
+
getRenderedMarkdown: function () {
|
| 124 |
+
return TEXT_PREFIX + marked(this.text.replace(this._mdDetector, '')) + TEXT_SUFFIX;
|
| 125 |
+
},
|
| 126 |
+
hasMarkdown: function () {
|
| 127 |
+
return this.text.indexOf(this._mdDetector) !== -1;
|
| 128 |
}
|
|
|
|
| 129 |
}
|
| 130 |
|
| 131 |
this.renderMarkdown = renderMarkdown;
|
| 132 |
+
this.mdExternalUrl = mdExternalUrl;
|
| 133 |
this.toggleMarkdown = toggleMarkdown;
|
| 134 |
|
| 135 |
+
document.observe('dom:loaded', function () {
|
| 136 |
+
var markdownLivePreview = $('markdown_live_preview');
|
| 137 |
+
if (markdownLivePreview) {
|
| 138 |
+
_livePreview(markdownLivePreview);
|
| 139 |
+
}
|
| 140 |
+
});
|
| 141 |
+
|
| 142 |
}).call(function () {
|
| 143 |
return this || (typeof window !== 'undefined' ? window : global);
|
| 144 |
}());
|
js/mage/adminhtml/marked.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
| 17 |
hr: /^( *[-*_]){3,} *(?:\n+|$)/,
|
| 18 |
heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
|
| 19 |
nptable: noop,
|
| 20 |
-
lheading: /^([^\n]+)\n *(=|-){
|
| 21 |
blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
|
| 22 |
list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
|
| 23 |
html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
|
|
@@ -75,7 +75,9 @@
|
|
| 75 |
});
|
| 76 |
|
| 77 |
block.gfm.paragraph = replace(block.paragraph)
|
| 78 |
-
('(?!', '(?!'
|
|
|
|
|
|
|
| 79 |
();
|
| 80 |
|
| 81 |
/**
|
|
@@ -320,7 +322,7 @@
|
|
| 320 |
// for discount behavior.
|
| 321 |
loose = next || /\n\n(?!\s*$)/.test(item);
|
| 322 |
if (i !== l - 1) {
|
| 323 |
-
next = item
|
| 324 |
if (!loose) loose = next;
|
| 325 |
}
|
| 326 |
|
|
@@ -352,7 +354,7 @@
|
|
| 352 |
type: this.options.sanitize
|
| 353 |
? 'paragraph'
|
| 354 |
: 'html',
|
| 355 |
-
pre: cap[1] === 'pre' || cap[1] === 'script',
|
| 356 |
text: cap[0]
|
| 357 |
});
|
| 358 |
continue;
|
|
@@ -407,7 +409,7 @@
|
|
| 407 |
src = src.substring(cap[0].length);
|
| 408 |
this.tokens.push({
|
| 409 |
type: 'paragraph',
|
| 410 |
-
text: cap[1]
|
| 411 |
? cap[1].slice(0, -1)
|
| 412 |
: cap[1]
|
| 413 |
});
|
|
@@ -454,8 +456,8 @@
|
|
| 454 |
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
|
| 455 |
};
|
| 456 |
|
| 457 |
-
inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
|
| 458 |
-
inline._href = /\s*<?([
|
| 459 |
|
| 460 |
inline.link = replace(inline.link)
|
| 461 |
('inside', inline._inside)
|
|
@@ -567,7 +569,7 @@
|
|
| 567 |
if (cap = this.rules.autolink.exec(src)) {
|
| 568 |
src = src.substring(cap[0].length);
|
| 569 |
if (cap[2] === '@') {
|
| 570 |
-
text = cap[1]
|
| 571 |
? this.mangle(cap[1].substring(7))
|
| 572 |
: this.mangle(cap[1]);
|
| 573 |
href = this.mangle('mailto:') + text;
|
|
@@ -622,7 +624,7 @@
|
|
| 622 |
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
|
| 623 |
link = this.links[link.toLowerCase()];
|
| 624 |
if (!link || !link.href) {
|
| 625 |
-
out += cap[0]
|
| 626 |
src = cap[0].substring(1) + src;
|
| 627 |
continue;
|
| 628 |
}
|
|
@@ -694,7 +696,7 @@
|
|
| 694 |
*/
|
| 695 |
|
| 696 |
InlineLexer.prototype.outputLink = function (cap, link) {
|
| 697 |
-
if (cap[0]
|
| 698 |
return '<a href="'
|
| 699 |
+ escape(link.href)
|
| 700 |
+ '"'
|
|
@@ -728,9 +730,17 @@
|
|
| 728 |
InlineLexer.prototype.smartypants = function (text) {
|
| 729 |
if (!this.options.smartypants) return text;
|
| 730 |
return text
|
|
|
|
| 731 |
.replace(/--/g, '\u2014')
|
| 732 |
-
|
| 733 |
-
.replace(/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 734 |
.replace(/\.{3}/g, '\u2026');
|
| 735 |
};
|
| 736 |
|
|
@@ -838,7 +848,9 @@
|
|
| 838 |
{
|
| 839 |
return '<h'
|
| 840 |
+ this.token.depth
|
| 841 |
-
+ '
|
|
|
|
|
|
|
| 842 |
+ this.inline.output(this.token.text)
|
| 843 |
+ '</h'
|
| 844 |
+ this.token.depth
|
|
@@ -882,9 +894,11 @@
|
|
| 882 |
body += '<thead>\n<tr>\n';
|
| 883 |
for (i = 0; i < this.token.header.length; i++) {
|
| 884 |
heading = this.inline.output(this.token.header[i]);
|
| 885 |
-
body +=
|
| 886 |
-
|
| 887 |
-
|
|
|
|
|
|
|
| 888 |
}
|
| 889 |
body += '</tr>\n</thead>\n';
|
| 890 |
|
|
@@ -895,9 +909,11 @@
|
|
| 895 |
body += '<tr>\n';
|
| 896 |
for (j = 0; j < row.length; j++) {
|
| 897 |
cell = this.inline.output(row[j]);
|
| 898 |
-
body +=
|
| 899 |
-
|
| 900 |
-
|
|
|
|
|
|
|
| 901 |
}
|
| 902 |
body += '</tr>\n';
|
| 903 |
}
|
|
@@ -1041,7 +1057,7 @@
|
|
| 1041 |
opt = null;
|
| 1042 |
}
|
| 1043 |
|
| 1044 |
-
|
| 1045 |
|
| 1046 |
var highlight = opt.highlight
|
| 1047 |
, tokens
|
|
@@ -1056,13 +1072,9 @@
|
|
| 1056 |
|
| 1057 |
pending = tokens.length;
|
| 1058 |
|
| 1059 |
-
var done = function (
|
| 1060 |
var out, err;
|
| 1061 |
|
| 1062 |
-
if (hi !== true) {
|
| 1063 |
-
delete opt.highlight;
|
| 1064 |
-
}
|
| 1065 |
-
|
| 1066 |
try {
|
| 1067 |
out = Parser.parse(tokens, opt);
|
| 1068 |
} catch (e) {
|
|
@@ -1077,9 +1089,11 @@
|
|
| 1077 |
};
|
| 1078 |
|
| 1079 |
if (!highlight || highlight.length < 3) {
|
| 1080 |
-
return done(
|
| 1081 |
}
|
| 1082 |
|
|
|
|
|
|
|
| 1083 |
if (!pending) return done();
|
| 1084 |
|
| 1085 |
for (; i < tokens.length; i++) {
|
|
@@ -1164,4 +1178,4 @@
|
|
| 1164 |
|
| 1165 |
}).call(function () {
|
| 1166 |
return this || (typeof window !== 'undefined' ? window : global);
|
| 1167 |
-
}());
|
| 17 |
hr: /^( *[-*_]){3,} *(?:\n+|$)/,
|
| 18 |
heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
|
| 19 |
nptable: noop,
|
| 20 |
+
lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
|
| 21 |
blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
|
| 22 |
list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
|
| 23 |
html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
|
| 75 |
});
|
| 76 |
|
| 77 |
block.gfm.paragraph = replace(block.paragraph)
|
| 78 |
+
('(?!', '(?!'
|
| 79 |
+
+ block.gfm.fences.source.replace('\\1', '\\2') + '|'
|
| 80 |
+
+ block.list.source.replace('\\1', '\\3') + '|')
|
| 81 |
();
|
| 82 |
|
| 83 |
/**
|
| 322 |
// for discount behavior.
|
| 323 |
loose = next || /\n\n(?!\s*$)/.test(item);
|
| 324 |
if (i !== l - 1) {
|
| 325 |
+
next = item.charAt(item.length - 1) === '\n';
|
| 326 |
if (!loose) loose = next;
|
| 327 |
}
|
| 328 |
|
| 354 |
type: this.options.sanitize
|
| 355 |
? 'paragraph'
|
| 356 |
: 'html',
|
| 357 |
+
pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
|
| 358 |
text: cap[0]
|
| 359 |
});
|
| 360 |
continue;
|
| 409 |
src = src.substring(cap[0].length);
|
| 410 |
this.tokens.push({
|
| 411 |
type: 'paragraph',
|
| 412 |
+
text: cap[1].charAt(cap[1].length - 1) === '\n'
|
| 413 |
? cap[1].slice(0, -1)
|
| 414 |
: cap[1]
|
| 415 |
});
|
| 456 |
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
|
| 457 |
};
|
| 458 |
|
| 459 |
+
inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
|
| 460 |
+
inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
|
| 461 |
|
| 462 |
inline.link = replace(inline.link)
|
| 463 |
('inside', inline._inside)
|
| 569 |
if (cap = this.rules.autolink.exec(src)) {
|
| 570 |
src = src.substring(cap[0].length);
|
| 571 |
if (cap[2] === '@') {
|
| 572 |
+
text = cap[1].charAt(6) === ':'
|
| 573 |
? this.mangle(cap[1].substring(7))
|
| 574 |
: this.mangle(cap[1]);
|
| 575 |
href = this.mangle('mailto:') + text;
|
| 624 |
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
|
| 625 |
link = this.links[link.toLowerCase()];
|
| 626 |
if (!link || !link.href) {
|
| 627 |
+
out += cap[0].charAt(0);
|
| 628 |
src = cap[0].substring(1) + src;
|
| 629 |
continue;
|
| 630 |
}
|
| 696 |
*/
|
| 697 |
|
| 698 |
InlineLexer.prototype.outputLink = function (cap, link) {
|
| 699 |
+
if (cap[0].charAt(0) !== '!') {
|
| 700 |
return '<a href="'
|
| 701 |
+ escape(link.href)
|
| 702 |
+ '"'
|
| 730 |
InlineLexer.prototype.smartypants = function (text) {
|
| 731 |
if (!this.options.smartypants) return text;
|
| 732 |
return text
|
| 733 |
+
// em-dashes
|
| 734 |
.replace(/--/g, '\u2014')
|
| 735 |
+
// opening singles
|
| 736 |
+
.replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
|
| 737 |
+
// closing singles & apostrophes
|
| 738 |
+
.replace(/'/g, '\u2019')
|
| 739 |
+
// opening doubles
|
| 740 |
+
.replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
|
| 741 |
+
// closing doubles
|
| 742 |
+
.replace(/"/g, '\u201d')
|
| 743 |
+
// ellipses
|
| 744 |
.replace(/\.{3}/g, '\u2026');
|
| 745 |
};
|
| 746 |
|
| 848 |
{
|
| 849 |
return '<h'
|
| 850 |
+ this.token.depth
|
| 851 |
+
+ ' id="'
|
| 852 |
+
+ this.token.text.toLowerCase().replace(/[^\w]+/g, '-')
|
| 853 |
+
+ '">'
|
| 854 |
+ this.inline.output(this.token.text)
|
| 855 |
+ '</h'
|
| 856 |
+ this.token.depth
|
| 894 |
body += '<thead>\n<tr>\n';
|
| 895 |
for (i = 0; i < this.token.header.length; i++) {
|
| 896 |
heading = this.inline.output(this.token.header[i]);
|
| 897 |
+
body += '<th';
|
| 898 |
+
if (this.token.align[i]) {
|
| 899 |
+
body += ' style="text-align:' + this.token.align[i] + '"';
|
| 900 |
+
}
|
| 901 |
+
body += '>' + heading + '</th>\n';
|
| 902 |
}
|
| 903 |
body += '</tr>\n</thead>\n';
|
| 904 |
|
| 909 |
body += '<tr>\n';
|
| 910 |
for (j = 0; j < row.length; j++) {
|
| 911 |
cell = this.inline.output(row[j]);
|
| 912 |
+
body += '<td';
|
| 913 |
+
if (this.token.align[j]) {
|
| 914 |
+
body += ' style="text-align:' + this.token.align[j] + '"';
|
| 915 |
+
}
|
| 916 |
+
body += '>' + cell + '</td>\n';
|
| 917 |
}
|
| 918 |
body += '</tr>\n';
|
| 919 |
}
|
| 1057 |
opt = null;
|
| 1058 |
}
|
| 1059 |
|
| 1060 |
+
opt = merge({}, marked.defaults, opt || {});
|
| 1061 |
|
| 1062 |
var highlight = opt.highlight
|
| 1063 |
, tokens
|
| 1072 |
|
| 1073 |
pending = tokens.length;
|
| 1074 |
|
| 1075 |
+
var done = function () {
|
| 1076 |
var out, err;
|
| 1077 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1078 |
try {
|
| 1079 |
out = Parser.parse(tokens, opt);
|
| 1080 |
} catch (e) {
|
| 1089 |
};
|
| 1090 |
|
| 1091 |
if (!highlight || highlight.length < 3) {
|
| 1092 |
+
return done();
|
| 1093 |
}
|
| 1094 |
|
| 1095 |
+
delete opt.highlight;
|
| 1096 |
+
|
| 1097 |
if (!pending) return done();
|
| 1098 |
|
| 1099 |
for (; i < tokens.length; i++) {
|
| 1178 |
|
| 1179 |
}).call(function () {
|
| 1180 |
return this || (typeof window !== 'undefined' ? window : global);
|
| 1181 |
+
}());
|
package.xml
CHANGED
|
@@ -1,28 +1,30 @@
|
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<package>
|
| 3 |
<name>markdown</name>
|
| 4 |
-
<version>1.
|
| 5 |
<stability>stable</stability>
|
| 6 |
<license uri="https://github.com/SchumacherFM/Magento-Markdown">Custom</license>
|
| 7 |
<channel>community</channel>
|
| 8 |
<extends/>
|
| 9 |
-
<summary>Markdown as module for Magento! Replaces the TinyMCE editor. Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).</summary>
|
| 10 |
-
<description>Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).
|
| 11 |

|
| 12 |
Full documentation of Markdown's syntax is available on John's Markdown page: http://daringfireball.net/projects/markdown/
|
| 13 |

|
| 14 |
Full support of Markdown Extra: http://michelf.ca/projects/php-markdown/extra/
|
| 15 |

|
| 16 |
-
This module renders all CMS pages and
|
| 17 |

|
| 18 |
Rendering of catalog description fields have to be implemented in the phtml files by yourself.
|
| 19 |

|
| 20 |
-
Preview in the backend.
|
|
|
|
|
|
|
| 21 |
<notes>https://github.com/SchumacherFM/Magento-Markdown</notes>
|
| 22 |
<authors><author><name>Cyrill Schumacher</name><user>cyrills</user><email>cyrill@schumacher.fm</email></author></authors>
|
| 23 |
-
<date>2013-09-
|
| 24 |
-
<time>
|
| 25 |
-
<contents><target name="magecommunity"><dir name="SchumacherFM"><dir name="Markdown"><dir><dir name="Helper"><file name="Data.php" hash="
|
| 26 |
<compatible/>
|
| 27 |
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
| 28 |
</package>
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<package>
|
| 3 |
<name>markdown</name>
|
| 4 |
+
<version>1.4.0</version>
|
| 5 |
<stability>stable</stability>
|
| 6 |
<license uri="https://github.com/SchumacherFM/Magento-Markdown">Custom</license>
|
| 7 |
<channel>community</channel>
|
| 8 |
<extends/>
|
| 9 |
+
<summary>Mage Markdown as module for Magento! Replaces the TinyMCE editor. Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).</summary>
|
| 10 |
+
<description>Mage Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).
|
| 11 |

|
| 12 |
Full documentation of Markdown's syntax is available on John's Markdown page: http://daringfireball.net/projects/markdown/
|
| 13 |

|
| 14 |
Full support of Markdown Extra: http://michelf.ca/projects/php-markdown/extra/
|
| 15 |

|
| 16 |
+
This module renders all CMS pages and CMS blocks.
|
| 17 |

|
| 18 |
Rendering of catalog description fields have to be implemented in the phtml files by yourself.
|
| 19 |

|
| 20 |
+
Preview in the backend. Live preview available in CMS Pages.
|
| 21 |
+

|
| 22 |
+
For further information please see the github repository: https://github.com/SchumacherFM/Magento-Markdown</description>
|
| 23 |
<notes>https://github.com/SchumacherFM/Magento-Markdown</notes>
|
| 24 |
<authors><author><name>Cyrill Schumacher</name><user>cyrills</user><email>cyrill@schumacher.fm</email></author></authors>
|
| 25 |
+
<date>2013-09-08</date>
|
| 26 |
+
<time>10:27:17</time>
|
| 27 |
+
<contents><target name="magecommunity"><dir name="SchumacherFM"><dir name="Markdown"><dir><dir name="Helper"><file name="Data.php" hash="35789036d57008a39effa53ed597d737"/></dir><dir name="Model"><dir name="Editor"><file name="Config.php" hash="44c6244ec440e8150778079cd184e5de"/><file name="Observer.php" hash="ad29b486cbe198b89e04db266d10c16b"/></dir><dir name="Markdown"><file name="Abstract.php" hash="496f33e550c20301a8a4c62c5cbf35a2"/><file name="Interface.php" hash="05df0ecf7a7c6bc09481f213cdc98255"/><file name="Observer.php" hash="e357583f380bcc925cc663d44f6120da"/><file name="Render.php" hash="df0addc5cfbd8d805c0b8a1661bbd496"/></dir><dir name="Michelf"><dir name="Markdown"><file name="Extra.php" hash="aaee7a66298007f8c003ba96d53deab9"/><file name="TmpImpl.php" hash="5ec68c28519d8ecb4a43324f5f197a80"/></dir><file name="Markdown.php" hash="76219ba32f37cad14755c8613b390c83"/></dir><dir name="Observer"><file name="AdminhtmlBlock.php" hash="50f7c3f848f847ef7b35206f7f48914f"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="MarkdownController.php" hash="9a7e8a64624159af49a18ad135d721ae"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="1f4034751ea0e0eece21d0015ee95e1a"/><file name="config.xml" hash="e398afbbb64dc97de74baf605ebc64fc"/><file name="system.xml" hash="0cee296bcf061251c7eab51dfefe224f"/></dir><dir name="sql"><dir name="markdown_setup"><file name="install-1.0.0.php" hash="0fe5a9650dd224f691caf585a34c52e6"/></dir></dir></dir><file name=".DS_Store" hash="29236c1e2932a8a54035bfbe9e734f49"/></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="markdown.xml" hash="ceece632ae2ebda2c33f7a7a37f9d7d2"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="SchumacherFM_Markdown.xml" hash="db8742448ef30a5af1bd60865f429c26"/></dir></target><target name="magelocale"><dir><dir name="de_DE"><file name="SchumacherFM_Markdown.csv" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir><dir name="en_US"><file name="SchumacherFM_Markdown.csv" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir></dir></target><target name="mage"><dir name="js"><dir name="mage"><dir name="adminhtml"><file name="markdown.js" hash="62a8ef8105db7defd76fa9f8bca6bfce"/><file name="marked.js" hash="5dbb480da6528c11cd99f3d17cc6aad5"/></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><file name="markdown.css" hash="68699f62ea8666484819346ff143ee88"/></dir></dir></dir></target></contents>
|
| 28 |
<compatible/>
|
| 29 |
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
| 30 |
</package>
|
