markdown - Version 1.4.0

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 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 $options
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, TRUE);
26
  }
27
 
28
  /**
29
- * @todo if backend check for current selected store view / website
30
  *
31
- * @return bool
32
  */
33
- public function getDetectionTag()
34
  {
35
- return Mage::getStoreConfig('schumacherfm/markdown/detection_tag');
 
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 bool
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  */
56
- public function isMarkdownExtra()
57
  {
58
- return (boolean)Mage::getStoreConfig('schumacherfm/markdown/md_extra');
 
 
 
 
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
- $onclickParts = array(
21
  'search' => array('html_id'),
22
- 'subject' => 'renderMarkdown(\'{{html_id}}\');'
23
  );
24
- $onclickPartsSyntax = array(
25
  'search' => array('html_id'),
26
- 'subject' => 'markdownSyntax(\'http://daringfireball.net/projects/markdown/syntax\',\'{{html_id}}\');'
27
  );
28
  $variableWysiwygPlugin = array(
29
  array(
30
  'name' => 'markdownToggle',
31
  'src' => '',
32
  'options' => array(
33
- 'title' => Mage::helper('markdown')->__('MD enable'),
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')->__('MD Preview'),
49
  'url' => '',
50
- 'onclick' => $onclickParts,
51
  'class' => 'plugin'
52
  )
53
  ),
54
  array(
55
- 'name' => 'markdownsyntax',
56
  'src' => '',
57
  'options' => array(
58
- 'title' => Mage::helper('markdown')->__('MD Syntax'),
59
  'url' => '',
60
- 'onclick' => $onclickPartsSyntax,
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')->__('MD Extra Syntax'),
72
  'url' => '',
73
  'onclick' => array(
74
  'search' => array('html_id'),
75
- 'subject' => 'markdownSyntax(\'http://michelf.ca/projects/php-markdown/extra/\',\'{{html_id}}\');'
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 Mage_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_Element) {
25
- /** @var $block Mage_Adminhtml_Block_Catalog_Form_Renderer_Fieldset_Element */
 
26
 
 
 
 
 
 
 
 
 
 
 
 
27
  /** @var Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg $element */
28
  $element = $block->getElement();
29
- if ($this->_isElementAllowed($element)) {
30
  $this->_getMarkdownButtons($element);
31
  }
32
  }
@@ -37,7 +51,19 @@ class SchumacherFM_Markdown_Model_Observer_AdminhtmlBlock
37
  *
38
  * @return bool
39
  */
40
- protected function _isElementAllowed(Varien_Data_Form_Element_Abstract $element)
 
 
 
 
 
 
 
 
 
 
 
 
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 = $element->getData('after_element_html');
 
53
 
54
- $html .= Mage::getSingleton('core/layout')
55
  ->createBlock('adminhtml/widget_button', '', array(
56
- 'label' => Mage::helper('markdown')->__('MD enable'),
57
  'type' => 'button',
58
  'class' => 'btn-wysiwyg',
59
- 'onclick' => 'toggleMarkdown(\'' .
60
- rawurlencode(Mage::helper('markdown')->getDetectionTag())
61
- . '\',\'' . $element->getHtmlId() . '\');'
62
- ))->toHtml().' ';
63
 
64
- $html .= Mage::getSingleton('core/layout')
65
  ->createBlock('adminhtml/widget_button', '', array(
66
- 'label' => Mage::helper('catalog')->__('Preview Markdown'),
67
  'type' => 'button',
68
  'class' => 'btn-wysiwyg',
69
- 'onclick' => 'renderMarkdown(\'' . $element->getHtmlId() . '\')'
70
  ))->toHtml();
71
 
72
- $element->setData('after_element_html', $html);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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/markdown_render</class>
44
- <method>renderPageObserver</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/markdown_render</class>
54
- <method>renderBlockObserver</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.</comment>
 
 
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 &lt;style&gt; 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
- <editor>
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 FORM_ID = 'edit_form';
10
- var dialogWindow;
11
- var dialogWindowId = 'markdown-preview';
12
- var TEXT_PREFIX = '<div class="markdown">';
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
- var closeDialogWindow = function (window) {
38
- if (!window) {
39
- window = dialogWindow;
40
- }
41
- if (window) {
42
- window.close();
43
- }
44
- }
45
 
46
- var _renderJs = function () {
47
- showPreview(marked($(htmlId).value));
48
- }
49
 
50
- var renderMarkdown = function (Idhtml) {
51
- htmlId = Idhtml;
52
- _renderJs();
53
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- }
 
 
 
 
 
 
 
56
 
57
- var markdownSyntax = function (url, Idhtml) {
58
- htmlId = Idhtml;
59
- window.open(url);
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
- var toggleMarkdown = function (detectionTag, Idhtml) {
63
- detectionTag = unescape(detectionTag);
64
 
65
- if ($(Idhtml).value.indexOf(detectionTag) === -1) {
66
- $(Idhtml).value = detectionTag + "\n" + $(Idhtml).value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
- alert('Markdown enabled with tag: "' + detectionTag+'"');
69
  }
70
 
71
  this.renderMarkdown = renderMarkdown;
72
- this.markdownSyntax = markdownSyntax;
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 *(=|-){3,} *\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
- ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
 
 
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[item.length - 1] === '\n';
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][cap[1].length - 1] === '\n'
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*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\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][6] === ':'
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][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][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
- .replace(/'([^']*)'/g, '\u2018$1\u2019')
733
- .replace(/"([^"]*)"/g, '\u201C$1\u201D')
 
 
 
 
 
 
 
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 += this.token.align[i]
886
- ? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n'
887
- : '<th>' + heading + '</th>\n';
 
 
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 += this.token.align[j]
899
- ? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n'
900
- : '<td>' + cell + '</td>\n';
 
 
901
  }
902
  body += '</tr>\n';
903
  }
@@ -1041,7 +1057,7 @@
1041
  opt = null;
1042
  }
1043
 
1044
- if (opt) opt = merge({}, marked.defaults, opt);
1045
 
1046
  var highlight = opt.highlight
1047
  , tokens
@@ -1056,13 +1072,9 @@
1056
 
1057
  pending = tokens.length;
1058
 
1059
- var done = function (hi) {
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(true);
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.1.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>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).&#xD;
11
  &#xD;
12
  Full documentation of Markdown's syntax is available on John's Markdown page: http://daringfireball.net/projects/markdown/&#xD;
13
  &#xD;
14
  Full support of Markdown Extra: http://michelf.ca/projects/php-markdown/extra/&#xD;
15
  &#xD;
16
- This module renders all CMS pages and every block which extends Mage_Core_Block_Abstract.&#xD;
17
  &#xD;
18
  Rendering of catalog description fields have to be implemented in the phtml files by yourself.&#xD;
19
  &#xD;
20
- Preview in the backend. No live preview available maybe later.</description>
 
 
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-02</date>
24
- <time>11:14:49</time>
25
- <contents><target name="magecommunity"><dir name="SchumacherFM"><dir name="Markdown"><dir><dir name="Helper"><file name="Data.php" hash="f9d8f27ac5f1080d7756284757833e37"/></dir><dir name="Model"><dir name="Editor"><file name="Config.php" hash="8d7361dbb53065a36cc2aaf4899107f2"/><file name="Observer.php" hash="ad29b486cbe198b89e04db266d10c16b"/></dir><dir name="Markdown"><file name="Render.php" hash="f077f2f523d932c9b8e6100403afe511"/></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="bb4d4c2b2b0c18d1b2970c1afbf110a4"/></dir><dir name="Observer"><file name="AdminhtmlBlock.php" hash="9b2464dba37e1cf829503d03e7477ad3"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="82b1eef25a4af5d8499deb8350a729bb"/><file name="config.xml" hash="05f418947ca0509a8fdb5477b936cff1"/><file name="system.xml" hash="e4ae8261f23405dcee3985070896cb08"/></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="43a7d9575776d74fc3dbd185445729f8"/></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="83c9424fcfebbebd30ebaa010ed214b6"/><file name="marked.js" hash="1fa57589a791297ce906795692f0252e"/></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>
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).&#xD;
11
  &#xD;
12
  Full documentation of Markdown's syntax is available on John's Markdown page: http://daringfireball.net/projects/markdown/&#xD;
13
  &#xD;
14
  Full support of Markdown Extra: http://michelf.ca/projects/php-markdown/extra/&#xD;
15
  &#xD;
16
+ This module renders all CMS pages and CMS blocks.&#xD;
17
  &#xD;
18
  Rendering of catalog description fields have to be implemented in the phtml files by yourself.&#xD;
19
  &#xD;
20
+ Preview in the backend. Live preview available in CMS Pages.&#xD;
21
+ &#xD;
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>