Skip to content

Commit 1c36a2f

Browse files
author
Sealan Cronin
committed
Initial commit.
0 parents  commit 1c36a2f

9 files changed

+221
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.DS_Store

_config.php

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
define('MARKDOWN_MODULE_BASE', basename(dirname(__FILE__)));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Class MarkdownSiteTreeExtension
4+
*
5+
* @package markdown
6+
* @subpackage extensions
7+
*/
8+
class MarkdownSiteTreeExtension extends DataExtension
9+
{
10+
private static $db = array(
11+
"Content" => "Text"
12+
);
13+
14+
/**
15+
* updateCMSFields
16+
* Replaces all instances of HtmlEditorField with MarkdownField.
17+
*
18+
* @param FieldList $fields
19+
*/
20+
public function updateCMSFields(FieldList $fields) {
21+
foreach($fields->dataFields() as $field) {
22+
if($field instanceof HtmlEditorField) {
23+
$markdownEditorField = new MarkdownEditorField($field->name, $field->title, 30);
24+
$fields->replaceField($field->name, $markdownEditorField);
25+
}
26+
}
27+
}
28+
29+
/**
30+
* Content
31+
* Parses Markdown to HTML.
32+
*
33+
* @return string Parsed HTML
34+
*/
35+
public function Content() {
36+
$content = $this->owner->Content;
37+
// Replace variables with CMS content.
38+
$data = $this->owner->toMap();
39+
foreach ($data as $field => $value) {
40+
$field = "$" . $field;
41+
$content = str_replace($field, $value, $content);
42+
}
43+
$parser = new Parsedown();
44+
return $parser->text($content);
45+
}
46+
}

code/forms/MarkdownEditorField.php

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* Class MarkdownField
4+
*
5+
* @package markdown
6+
* @subpackage forms
7+
*/
8+
class MarkdownEditorField extends TextareaField
9+
{
10+
/**
11+
* @var int $rows Number of rows in textarea element.
12+
*/
13+
protected $rows = 20;
14+
15+
public function FieldHolder($properties = array()) {
16+
$this->extraClasses['stacked'] = 'stacked';
17+
18+
Requirements::css(MARKDOWN_MODULE_BASE . '/css/MarkdownEditor.css');
19+
20+
Requirements::javascript(MARKDOWN_MODULE_BASE . '/thirdparty/ace/ace.min.js');
21+
Requirements::javascript(MARKDOWN_MODULE_BASE . '/thirdparty/ace/mode-markdown.min.js');
22+
Requirements::javascript(MARKDOWN_MODULE_BASE . '/thirdparty/ace/theme-github.min.js');
23+
24+
Requirements::javascript(MARKDOWN_MODULE_BASE . '/javascript/MarkdownEditor.js');
25+
26+
return parent::FieldHolder($properties);
27+
}
28+
}

css/MarkdownEditor.css

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.markdowneditor .middleColumn {
2+
border: none;
3+
}
4+
5+
.markdowneditor .markdowneditor_editor {
6+
border: 1px solid #CCCCCC;
7+
position: relative;
8+
font-family: Monaco, "Liberation Mono", Courier, monospace;
9+
z-index: 0;
10+
}
11+
12+
.markdowneditor .markdowneditor_editor .ace_content {
13+
line-height: normal;
14+
}
15+
16+
.markdowneditor .ace_focus {
17+
border: 1px solid #9a9a9a;
18+
border-top-color: #808080;
19+
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) inset;
20+
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) inset;
21+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) inset;
22+
}

javascript/MarkdownEditor.js

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
(function($) {
2+
$.entwine('ss', function($) {
3+
$('textarea.markdowneditor').entwine({
4+
TextArea: null,
5+
Div: null,
6+
Editor: null,
7+
Frame: null,
8+
SoftTabs: true,
9+
onmatch: function() {
10+
$(this).setFrame({
11+
width: '100%',
12+
height: $(this).height()
13+
});
14+
15+
$(this).setTextArea($(this));
16+
$(this).hide();
17+
18+
var div = $('<div id="'+$(this).attr('ID')+'_Editor" class="markdowneditor_editor"/>').css('height', $(this).getFrame().height).css('width', $(this).getFrame().width).text($(this).val());
19+
div.insertAfter($(this));
20+
$(this).setDiv(div);
21+
22+
var editor = ace.edit(div.get(0));
23+
editor.getSession().setMode('ace/mode/markdown');
24+
editor.setTheme('ace/theme/github');
25+
editor.resize();
26+
editor.$blockScrolling = Infinity;
27+
28+
// configure
29+
editor.getSession().setUseWrapMode(true);
30+
editor.getSession().setWrapLimitRange(80, 80);
31+
32+
editor.setShowPrintMargin(true);
33+
editor.renderer.setShowGutter(false);
34+
35+
$(this).setEditor(editor);
36+
37+
var code = $(this).val();
38+
39+
$(this).setUseSoftTabs($(this).usesSoftTabs(code));
40+
$(this).setTabSize($(this).getSoftTabs() ? $(this).guessTabSize(code):8);
41+
$(this).setupFormBindings();
42+
43+
$(this).setupKeyBindings();
44+
},
45+
code: function() {
46+
return $(this).getEditor().getSession().getValue();
47+
},
48+
setupFormBindings: function() {
49+
var self=$(this);
50+
$(this).getEditor().getSession().on("change", function() {
51+
self.getTextArea().val(self.code()).change();
52+
});
53+
},
54+
setUseSoftTabs: function(val) {
55+
$(this).setSoftTabs(val);
56+
$(this).getEditor().getSession().setUseSoftTabs(val);
57+
},
58+
setTabSize: function(val) {
59+
$(this).getEditor().getSession().setTabSize(val);
60+
},
61+
setUseWrapMode: function(val) {
62+
$(this).getEditor().getSession().setUseWrapMode(val);
63+
},
64+
guessTabSize: function(val) {
65+
var result=/^( +)[^*]/im.exec(val || $(this).code());
66+
return (result ? result[1].length:2);
67+
},
68+
usesSoftTabs: function(val) {
69+
return !/^\t/m.test(val || $(this).code());
70+
},
71+
setupKeyBindings: function() {
72+
$(this).getEditor().commands.addCommand({
73+
name: "bold",
74+
bindKey: {
75+
win: "Ctrl-B",
76+
mac: "Command-B"
77+
},
78+
exec: function(editor) {
79+
if (editor.selection.isEmpty()) {
80+
var content = "****";
81+
82+
editor.insert(content);
83+
editor.selection.moveCursorBy(0, -2);
84+
85+
var cursor = editor.selection.getCursor();
86+
editor.selection.selectTo(cursor.row, cursor.column);
87+
} else {
88+
var content = editor.session.getTextRange(editor.getSelectionRange());
89+
90+
if ("**" == content.substring(0, 2) && "**" == content.substring(content.length - 2)) {
91+
content = content.replace(/\*/g, "");
92+
editor.insert(content);
93+
} else {
94+
content = "**" + content + "**";
95+
editor.insert(content);
96+
}
97+
98+
var cursor = editor.selection.getCursor();
99+
editor.selection.moveCursorBy(0, 0 - content.length);
100+
cursor = editor.selection.getCursor();
101+
editor.selection.selectTo(cursor.row, cursor.column + content.length);
102+
}
103+
}
104+
});
105+
}
106+
});
107+
});
108+
})(jQuery);

thirdparty/ace/ace.min.js

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

thirdparty/ace/mode-markdown.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

thirdparty/ace/theme-github.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)