rails-bootstrap-markdown 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +45 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/bootstrap-markdown.js +989 -0
- data/app/assets/javascripts/markdown.js +1642 -0
- data/app/assets/javascripts/to-markdown.js +184 -0
- data/app/assets/stylesheets/bootstrap-markdown.css.scss +62 -0
- data/lib/rails-bootstrap-markdown.rb +10 -0
- data/lib/rails-bootstrap-markdown/version.rb +7 -0
- data/rails-bootstrap-markdown.gemspec +18 -0
- metadata +63 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
/*
|
2
|
+
* to-markdown - an HTML to Markdown converter
|
3
|
+
*
|
4
|
+
* Copyright 2011, Dom Christie
|
5
|
+
* Licenced under the MIT licence
|
6
|
+
*
|
7
|
+
*/
|
8
|
+
|
9
|
+
var toMarkdown = function(string) {
|
10
|
+
|
11
|
+
var ELEMENTS = [
|
12
|
+
{
|
13
|
+
patterns: 'p',
|
14
|
+
replacement: function(str, attrs, innerHTML) {
|
15
|
+
return innerHTML ? '\n\n' + innerHTML + '\n' : '';
|
16
|
+
}
|
17
|
+
},
|
18
|
+
{
|
19
|
+
patterns: 'br',
|
20
|
+
type: 'void',
|
21
|
+
replacement: '\n'
|
22
|
+
},
|
23
|
+
{
|
24
|
+
patterns: 'h([1-6])',
|
25
|
+
replacement: function(str, hLevel, attrs, innerHTML) {
|
26
|
+
var hPrefix = '';
|
27
|
+
for(var i = 0; i < hLevel; i++) {
|
28
|
+
hPrefix += '#';
|
29
|
+
}
|
30
|
+
return '\n\n' + hPrefix + ' ' + innerHTML + '\n';
|
31
|
+
}
|
32
|
+
},
|
33
|
+
{
|
34
|
+
patterns: 'hr',
|
35
|
+
type: 'void',
|
36
|
+
replacement: '\n\n* * *\n'
|
37
|
+
},
|
38
|
+
{
|
39
|
+
patterns: 'a',
|
40
|
+
replacement: function(str, attrs, innerHTML) {
|
41
|
+
var href = attrs.match(attrRegExp('href')),
|
42
|
+
title = attrs.match(attrRegExp('title'));
|
43
|
+
return href ? '[' + innerHTML + ']' + '(' + href[1] + (title && title[1] ? ' "' + title[1] + '"' : '') + ')' : str;
|
44
|
+
}
|
45
|
+
},
|
46
|
+
{
|
47
|
+
patterns: ['b', 'strong'],
|
48
|
+
replacement: function(str, attrs, innerHTML) {
|
49
|
+
return innerHTML ? '**' + innerHTML + '**' : '';
|
50
|
+
}
|
51
|
+
},
|
52
|
+
{
|
53
|
+
patterns: ['i', 'em'],
|
54
|
+
replacement: function(str, attrs, innerHTML) {
|
55
|
+
return innerHTML ? '_' + innerHTML + '_' : '';
|
56
|
+
}
|
57
|
+
},
|
58
|
+
{
|
59
|
+
patterns: 'code',
|
60
|
+
replacement: function(str, attrs, innerHTML) {
|
61
|
+
return innerHTML ? '`' + innerHTML + '`' : '';
|
62
|
+
}
|
63
|
+
},
|
64
|
+
{
|
65
|
+
patterns: 'img',
|
66
|
+
type: 'void',
|
67
|
+
replacement: function(str, attrs, innerHTML) {
|
68
|
+
var src = attrs.match(attrRegExp('src')),
|
69
|
+
alt = attrs.match(attrRegExp('alt')),
|
70
|
+
title = attrs.match(attrRegExp('title'));
|
71
|
+
return '![' + (alt && alt[1] ? alt[1] : '') + ']' + '(' + src[1] + (title && title[1] ? ' "' + title[1] + '"' : '') + ')';
|
72
|
+
}
|
73
|
+
}
|
74
|
+
];
|
75
|
+
|
76
|
+
for(var i = 0, len = ELEMENTS.length; i < len; i++) {
|
77
|
+
if(typeof ELEMENTS[i].patterns === 'string') {
|
78
|
+
string = replaceEls(string, { tag: ELEMENTS[i].patterns, replacement: ELEMENTS[i].replacement, type: ELEMENTS[i].type });
|
79
|
+
}
|
80
|
+
else {
|
81
|
+
for(var j = 0, pLen = ELEMENTS[i].patterns.length; j < pLen; j++) {
|
82
|
+
string = replaceEls(string, { tag: ELEMENTS[i].patterns[j], replacement: ELEMENTS[i].replacement, type: ELEMENTS[i].type });
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
function replaceEls(html, elProperties) {
|
88
|
+
var pattern = elProperties.type === 'void' ? '<' + elProperties.tag + '\\b([^>]*)\\/?>' : '<' + elProperties.tag + '\\b([^>]*)>([\\s\\S]*?)<\\/' + elProperties.tag + '>',
|
89
|
+
regex = new RegExp(pattern, 'gi'),
|
90
|
+
markdown = '';
|
91
|
+
if(typeof elProperties.replacement === 'string') {
|
92
|
+
markdown = html.replace(regex, elProperties.replacement);
|
93
|
+
}
|
94
|
+
else {
|
95
|
+
markdown = html.replace(regex, function(str, p1, p2, p3) {
|
96
|
+
return elProperties.replacement.call(this, str, p1, p2, p3);
|
97
|
+
});
|
98
|
+
}
|
99
|
+
return markdown;
|
100
|
+
}
|
101
|
+
|
102
|
+
function attrRegExp(attr) {
|
103
|
+
return new RegExp(attr + '\\s*=\\s*["\']?([^"\']*)["\']?', 'i');
|
104
|
+
}
|
105
|
+
|
106
|
+
// Pre code blocks
|
107
|
+
|
108
|
+
string = string.replace(/<pre\b[^>]*>`([\s\S]*)`<\/pre>/gi, function(str, innerHTML) {
|
109
|
+
innerHTML = innerHTML.replace(/^\t+/g, ' '); // convert tabs to spaces (you know it makes sense)
|
110
|
+
innerHTML = innerHTML.replace(/\n/g, '\n ');
|
111
|
+
return '\n\n ' + innerHTML + '\n';
|
112
|
+
});
|
113
|
+
|
114
|
+
// Lists
|
115
|
+
|
116
|
+
// Escape numbers that could trigger an ol
|
117
|
+
// If there are more than three spaces before the code, it would be in a pre tag
|
118
|
+
// Make sure we are escaping the period not matching any character
|
119
|
+
string = string.replace(/^(\s{0,3}\d+)\. /g, '$1\\. ');
|
120
|
+
|
121
|
+
// Converts lists that have no child lists (of same type) first, then works it's way up
|
122
|
+
var noChildrenRegex = /<(ul|ol)\b[^>]*>(?:(?!<ul|<ol)[\s\S])*?<\/\1>/gi;
|
123
|
+
while(string.match(noChildrenRegex)) {
|
124
|
+
string = string.replace(noChildrenRegex, function(str) {
|
125
|
+
return replaceLists(str);
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
function replaceLists(html) {
|
130
|
+
|
131
|
+
html = html.replace(/<(ul|ol)\b[^>]*>([\s\S]*?)<\/\1>/gi, function(str, listType, innerHTML) {
|
132
|
+
var lis = innerHTML.split('</li>');
|
133
|
+
lis.splice(lis.length - 1, 1);
|
134
|
+
|
135
|
+
for(i = 0, len = lis.length; i < len; i++) {
|
136
|
+
if(lis[i]) {
|
137
|
+
var prefix = (listType === 'ol') ? (i + 1) + ". " : "* ";
|
138
|
+
lis[i] = lis[i].replace(/\s*<li[^>]*>([\s\S]*)/i, function(str, innerHTML) {
|
139
|
+
|
140
|
+
innerHTML = innerHTML.replace(/^\s+/, '');
|
141
|
+
innerHTML = innerHTML.replace(/\n\n/g, '\n\n ');
|
142
|
+
// indent nested lists
|
143
|
+
innerHTML = innerHTML.replace(/\n([ ]*)+(\*|\d+\.) /g, '\n$1 $2 ');
|
144
|
+
return prefix + innerHTML;
|
145
|
+
});
|
146
|
+
}
|
147
|
+
}
|
148
|
+
return lis.join('\n');
|
149
|
+
});
|
150
|
+
return '\n\n' + html.replace(/[ \t]+\n|\s+$/g, '');
|
151
|
+
}
|
152
|
+
|
153
|
+
// Blockquotes
|
154
|
+
var deepest = /<blockquote\b[^>]*>((?:(?!<blockquote)[\s\S])*?)<\/blockquote>/gi;
|
155
|
+
while(string.match(deepest)) {
|
156
|
+
string = string.replace(deepest, function(str) {
|
157
|
+
return replaceBlockquotes(str);
|
158
|
+
});
|
159
|
+
}
|
160
|
+
|
161
|
+
function replaceBlockquotes(html) {
|
162
|
+
html = html.replace(/<blockquote\b[^>]*>([\s\S]*?)<\/blockquote>/gi, function(str, inner) {
|
163
|
+
inner = inner.replace(/^\s+|\s+$/g, '');
|
164
|
+
inner = cleanUp(inner);
|
165
|
+
inner = inner.replace(/^/gm, '> ');
|
166
|
+
inner = inner.replace(/^(>([ \t]{2,}>)+)/gm, '> >');
|
167
|
+
return inner;
|
168
|
+
});
|
169
|
+
return html;
|
170
|
+
}
|
171
|
+
|
172
|
+
function cleanUp(string) {
|
173
|
+
string = string.replace(/^[\t\r\n]+|[\t\r\n]+$/g, ''); // trim leading/trailing whitespace
|
174
|
+
string = string.replace(/\n\s+\n/g, '\n\n');
|
175
|
+
string = string.replace(/\n{3,}/g, '\n\n'); // limit consecutive linebreaks to 2
|
176
|
+
return string;
|
177
|
+
}
|
178
|
+
|
179
|
+
return cleanUp(string);
|
180
|
+
};
|
181
|
+
|
182
|
+
if (typeof exports === 'object') {
|
183
|
+
exports.toMarkdown = toMarkdown;
|
184
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
/**
|
2
|
+
* Bootstrap-Markdown.css.scss
|
3
|
+
*
|
4
|
+
* Converted to SCSS by Danny Tatom @dannytatom
|
5
|
+
*
|
6
|
+
* @author Taufan Aditya @taufanaditya
|
7
|
+
* @copyright 2013 Taufan Aditya
|
8
|
+
*/
|
9
|
+
|
10
|
+
@import "bootstrap/variables";
|
11
|
+
@import "bootstrap/mixins";
|
12
|
+
|
13
|
+
.md-editor {
|
14
|
+
display: block;
|
15
|
+
border: 1px solid $tableBorder;
|
16
|
+
|
17
|
+
.md-header, .md-footer {
|
18
|
+
display: block;
|
19
|
+
padding: 6px 4px;
|
20
|
+
background: $white;
|
21
|
+
}
|
22
|
+
|
23
|
+
.md-preview {
|
24
|
+
background: $white;
|
25
|
+
border-top: 1px dashed $tableBorder;
|
26
|
+
border-bottom: 1px dashed $tableBorder;
|
27
|
+
min-height: 10px;
|
28
|
+
}
|
29
|
+
|
30
|
+
textarea {
|
31
|
+
font-family: $monoFontFamily;
|
32
|
+
font-size: $baseFontSize;
|
33
|
+
outline: 0;
|
34
|
+
outline: thin dotted \9; /* IE6-9 */
|
35
|
+
margin: 0;
|
36
|
+
display: block;
|
37
|
+
padding: 0;
|
38
|
+
width: 100%;
|
39
|
+
border: 0;
|
40
|
+
border-top: 1px dashed $tableBorder;
|
41
|
+
border-bottom: 1px dashed $tableBorder;
|
42
|
+
border-radius: 0;
|
43
|
+
box-shadow: none;
|
44
|
+
background: $inputDisabledBackground;
|
45
|
+
|
46
|
+
&:focus {
|
47
|
+
box-shadow: none;
|
48
|
+
background: $inputBackground;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
// Hover state
|
53
|
+
&.active {
|
54
|
+
@include box-shadow("inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6)");
|
55
|
+
|
56
|
+
border-color: rgba(82,168,236,.8);
|
57
|
+
outline: 0;
|
58
|
+
outline: thin dotted \9; /* IE6-9 */
|
59
|
+
|
60
|
+
@include transition(border linear .2s, box-shadow linear .2s);
|
61
|
+
}
|
62
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rails-bootstrap-markdown/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "rails-bootstrap-markdown"
|
8
|
+
gem.version = Rails::Bootstrap::Markdown::VERSION
|
9
|
+
gem.authors = ["Danny Tatom"]
|
10
|
+
gem.email = ["dannytatom@gmail.com"]
|
11
|
+
gem.summary = %q{A Rails gem for Bootstrap Markdown}
|
12
|
+
gem.homepage = "http://github.com/dannytatom/rails-bootstrap-markdown"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($/)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails-bootstrap-markdown
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Danny Tatom
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-11 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email:
|
16
|
+
- dannytatom@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE.txt
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- app/assets/javascripts/bootstrap-markdown.js
|
27
|
+
- app/assets/javascripts/markdown.js
|
28
|
+
- app/assets/javascripts/to-markdown.js
|
29
|
+
- app/assets/stylesheets/bootstrap-markdown.css.scss
|
30
|
+
- lib/rails-bootstrap-markdown.rb
|
31
|
+
- lib/rails-bootstrap-markdown/version.rb
|
32
|
+
- rails-bootstrap-markdown.gemspec
|
33
|
+
homepage: http://github.com/dannytatom/rails-bootstrap-markdown
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
hash: -2957847032896564447
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
hash: -2957847032896564447
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.8.23
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: A Rails gem for Bootstrap Markdown
|
63
|
+
test_files: []
|