ruby-shortcodes 0.0.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +5 -0
- data/lib/shortcodes.rb +7 -0
- data/lib/shortcodes/tuts_shortcodes.rb +213 -0
- data/lib/shortcodes/version.rb +3 -0
- data/lib/shortcodes/wordpress_shortcodes.rb +123 -0
- data/ruby-shortcodes.gemspec +27 -0
- data/spec/spec_helper.rb +0 -0
- data/spec/tuts_shortcodes_spec.rb +227 -0
- data/spec/wordpress_shortcodes_spec.rb +34 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5a12ee03c9450b72520304ba08bd79e3e1208894fa2f05aa85f1c93532de45c4
|
4
|
+
data.tar.gz: 21deb3f3b42687d9c9909ee7dfbc384ec8c9462547b7edba49d4e243449028b7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 77f08407d13f2164bb4e9c53c17735c6a14f749224db1f45466764165fba9bdf8e0875e943ba68cf556838ead15ecc75785aad0ea6572814063939cba657918b
|
7
|
+
data.tar.gz: d289ae34f8663272db408f81fb9b22f164cd8c80b17aff939f1d26068acc9f13045fe33bb64b90dc8a046a73488b05845a17197586167d717f0f0f1e513f3c60
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 David Lee
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Shortcodes for Ruby
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ruby-shortcodes'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ruby-shortcodes
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/shortcodes.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
module Shortcodes
|
2
|
+
class TutsShortcodes < WordpressShortcodes
|
3
|
+
|
4
|
+
SUPPORTED_SYNTAXES = %w(
|
5
|
+
as3 actionscript3
|
6
|
+
bash shell
|
7
|
+
cf coldfusion
|
8
|
+
c-sharp csharp
|
9
|
+
cpp c
|
10
|
+
objc obj-c
|
11
|
+
css
|
12
|
+
delphi pas pascal
|
13
|
+
diff patch
|
14
|
+
erl erlang
|
15
|
+
groovy
|
16
|
+
js jscript javascript
|
17
|
+
java
|
18
|
+
jfx javafx
|
19
|
+
perl pl
|
20
|
+
php
|
21
|
+
plain text
|
22
|
+
ps powershell
|
23
|
+
py python
|
24
|
+
rails ror ruby rb
|
25
|
+
scala
|
26
|
+
sql
|
27
|
+
vb vbnet
|
28
|
+
xml xhtml xslt html xhtml
|
29
|
+
)
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
super
|
33
|
+
|
34
|
+
add_shortcode 'sessions_post' do |att|
|
35
|
+
att = {
|
36
|
+
'href' => 'http://sessions.tutsplus.com/creative/',
|
37
|
+
'title' => 'Creative Sessions',
|
38
|
+
'day' => '1',
|
39
|
+
'prev' => '',
|
40
|
+
'next' => ''
|
41
|
+
}.merge att
|
42
|
+
|
43
|
+
navigation = ''
|
44
|
+
|
45
|
+
if att['prev'].present? || att['next'].present?
|
46
|
+
p = att['prev'].present? ? '<a href="' + att['prev'] + '" class="left">« Session Day ' + (att['day'].to_i - 1).to_s + '</a>' : ''
|
47
|
+
n = att['next'].present? ? '<a href="' + att['next'] + '" class="right">Session Day ' + (att['day'].to_i + 1).to_s + ' »</a>' : ''
|
48
|
+
navigation = '<div class="session_navigation" style="overflow:hidden;clear:both;padding-top:10px;">' + p + n + '</div>'
|
49
|
+
end
|
50
|
+
|
51
|
+
'<div class="sessions_post">This Post is Day ' + att['day'] + ' of our <a href="' + att['href'] + '">' + att['title'] + ' Session</a>. <a href="http://sessions.tutsplus.com/creative/" class="cs_span">Creative Sessions</a>' + navigation + '</div>'
|
52
|
+
end
|
53
|
+
|
54
|
+
add_shortcode 'sponsored_review' do
|
55
|
+
'<div class="review-shortcode"><strong>Sponsored Content</strong><p>This is a sponsored review or giveaway of a product/service that\'s particularly relevant to our readers.</p></div>'
|
56
|
+
end
|
57
|
+
|
58
|
+
add_shortcode 'sponsored_content' do |attr, content|
|
59
|
+
'<div class="sponsored-shortcode"><strong>Sponsored Content</strong><p>This content was commissioned by ' + content.strip + ' and was written and/or edited by the Tuts+ team. Our aim with sponsored content is to publish relevant and objective tutorials, case studies, and inspirational interviews that offer genuine educational value to our readers and enable us to fund the creation of more useful content.</p></div>'
|
60
|
+
end
|
61
|
+
|
62
|
+
add_shortcode 'disclaimer' do
|
63
|
+
'<div class="disclaimer-shortcode"><strong>Disclaimer</strong><p>You should always seek independent financial advice and thoroughly read terms and conditions relating to any insurance, tax, legal, or financial issue, service, or product. This article is intended as a guide only.</p></div>'
|
64
|
+
end
|
65
|
+
|
66
|
+
add_shortcode 'republished' do |attr, content|
|
67
|
+
'<div class="republished-shortcode"><strong>Republished Tutorial</strong><p>Every few weeks, we revisit some of our reader\'s favorite posts from throughout the history of the site. This tutorial was first published in ' + content + '.</p></div>'
|
68
|
+
end
|
69
|
+
|
70
|
+
add_shortcode 'changed' do |attr, content|
|
71
|
+
'<div class="changed-shortcode"><strong>Subsequent Changes to Techniques & Software</strong><p>Certain aspects of applications or techniques used in this tutorial have changed since it was originally published. This might make it a little difficult to follow along. We\'d recommend looking at these more recent tutorials on the same topic:</p>' + content + '</div>'
|
72
|
+
end
|
73
|
+
|
74
|
+
add_shortcode 'videodownload' do |attr, content|
|
75
|
+
'<div class="videodownload-shortcode"><strong>Download Video</strong>' + content + '</div>'
|
76
|
+
end
|
77
|
+
|
78
|
+
add_shortcode 'tip' do |attr, content|
|
79
|
+
if content
|
80
|
+
'<div class="tip-shortcode">' + content + '</div>';
|
81
|
+
else
|
82
|
+
''
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
add_shortcode 'related' do |attr, content|
|
87
|
+
'<div class="related-shortcode"><strong>Related Posts</strong>' + content + '</div>';
|
88
|
+
end
|
89
|
+
|
90
|
+
add_shortcode 'audio' do |att|
|
91
|
+
if att.respond_to? :last
|
92
|
+
att.delete(":")
|
93
|
+
audio_url = att.join(' ').gsub(/^:/, '')
|
94
|
+
type = nil
|
95
|
+
else
|
96
|
+
audio_url = att.values.last
|
97
|
+
codec = att.keys.first
|
98
|
+
type = case codec
|
99
|
+
when 'mp3'
|
100
|
+
%Q[type='audio/mpeg; codecs="mp3"']
|
101
|
+
when 'ogg','vorbis'
|
102
|
+
%Q[type='audio/ogg; codecs="vorbis"']
|
103
|
+
else
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
%Q[<audio src="#{audio_url}" #{type} />]
|
108
|
+
end
|
109
|
+
|
110
|
+
add_shortcode 'mathjax' do
|
111
|
+
'<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>'
|
112
|
+
end
|
113
|
+
|
114
|
+
handle_sourcecode = Proc.new do |att, content|
|
115
|
+
att = { 'language' => 'plain' } unless att.is_a?(Hash) # Use plain as the default
|
116
|
+
|
117
|
+
att['brush'] = att.delete('language') || att.delete('lang')
|
118
|
+
attrs = att.map do |k,v|
|
119
|
+
v = "[#{v}]" if k == 'highlight'
|
120
|
+
"#{k}: #{v}"
|
121
|
+
end.join('; ')
|
122
|
+
|
123
|
+
if content
|
124
|
+
# Not left-stripping content because we want to preserve any indentations
|
125
|
+
# at the start.
|
126
|
+
%(<pre class="#{attrs}">#{content.rstrip}</pre>)
|
127
|
+
else
|
128
|
+
''
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
add_shortcode 'sourcecode', &handle_sourcecode
|
133
|
+
add_shortcode 'code', &handle_sourcecode
|
134
|
+
|
135
|
+
SUPPORTED_SYNTAXES.each do |lang|
|
136
|
+
add_shortcode lang do |att, content|
|
137
|
+
new_att = { 'language' => lang }
|
138
|
+
new_att.merge!(att) if att.is_a? Hash
|
139
|
+
handle_sourcecode.call(new_att, content)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
add_shortcode 'quiz' do |att|
|
144
|
+
'<div id="quiz-container" style="margin-bottom: 30px;"></div>
|
145
|
+
<link rel="stylesheet" href="http://nettuts.s3.amazonaws.com/jquizzy-1.0/css/styles-cloud-version1.30.css" />
|
146
|
+
<script src="http://nettuts.s3.amazonaws.com/jquizzy-1.0/js/jquery.jquizzyv1.35.js"></script>
|
147
|
+
<script src="' + att['url'] + '"></script>
|
148
|
+
|
149
|
+
<script>
|
150
|
+
function initQuiz() {
|
151
|
+
if (window.init) {
|
152
|
+
$("#quiz-container").jquizzy({
|
153
|
+
questions: init.questions,
|
154
|
+
resultComments: init.resultComments,
|
155
|
+
twitterStatus: "Woo! I got {score} on the @envatopsd quiz. Try it! http://bit.ly/linky",
|
156
|
+
twitterUsername: "envatopsd",
|
157
|
+
twitterImage: "http://nettuts.s3.amazonaws.com/jquizzy-1.0/img/share.png",
|
158
|
+
splashImage: "' + att['image'] + '"
|
159
|
+
});
|
160
|
+
} else {
|
161
|
+
setTimeout(initQuiz, 100);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
$(document).ready(function() { initQuiz() });
|
165
|
+
</script>'
|
166
|
+
end
|
167
|
+
|
168
|
+
add_shortcode 'polldaddy' do |att|
|
169
|
+
%(<script type="text/javascript" charset="utf-8" src="http://static.polldaddy.com/p/#{att['id']}.js"></script>)
|
170
|
+
end
|
171
|
+
|
172
|
+
add_shortcode 'WP_UnityObject' do |att|
|
173
|
+
# The WP plugin generates an iframe tag to load another php script that embeds the actual content with some JS.
|
174
|
+
# To makes things simpler for us, we're going to load the object in place using this method instead (loosely):
|
175
|
+
# http://docs.unity3d.com/Documentation/Manual/HTMLcodetoloadUnityWebPlayercontent.html
|
176
|
+
#
|
177
|
+
# TODO: allow more than one of this in the same page.
|
178
|
+
#
|
179
|
+
# TODO: (less urgent) load the js from https://ssl-webplayer... when on SSL, could've used '//webplayer.unity3d.com'
|
180
|
+
# if unity3d were smarter :/
|
181
|
+
%Q{
|
182
|
+
<script src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js"></script>
|
183
|
+
<script async>$(function(){new UnityObject2().initPlugin($('.unity-player')[0], "#{att['src']}");});</script>
|
184
|
+
<div class="unity-player" style="width:#{att['width']}px;height:#{att['height']}px">
|
185
|
+
<div class="unity-player__missing">
|
186
|
+
<a href="http://unity3d.com/webplayer/">
|
187
|
+
<img alt="Unity Web Player. Install now!" src="http://webplayer.unity3d.com/installation/getunity.png" width="193" height="63" />
|
188
|
+
</a>
|
189
|
+
</div>
|
190
|
+
</div>
|
191
|
+
}.gsub(/\s+/, ' ').gsub(/>\s+</, '><').strip
|
192
|
+
end
|
193
|
+
|
194
|
+
add_shortcode 'caption' do |att, content|
|
195
|
+
if match = content.match(/^\s*(<img[^>]*>)\s*(.*)$/)
|
196
|
+
%(<figure class="post_image">#{match[1]}<figcaption>#{match[2]}</figcaption></figure>)
|
197
|
+
else
|
198
|
+
content
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
add_shortcode 'player' do |att|
|
203
|
+
if src = att['href']
|
204
|
+
width = att['width'] || "100%"
|
205
|
+
height = att['height'] || "auto"
|
206
|
+
%Q{
|
207
|
+
<video class="post__content-video" src="#{src}" width="#{width}" height="#{height}" />
|
208
|
+
}.strip
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'active_support/core_ext/object'
|
2
|
+
module Shortcodes
|
3
|
+
class WordpressShortcodes
|
4
|
+
# Ruby port of WordPress wp-includes/shortcodes
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@shortcode_tags = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(html)
|
11
|
+
if @shortcode_tags.any?
|
12
|
+
html.gsub(get_shortcode_regex){ do_shortcode_tag *($~.to_a) }
|
13
|
+
else
|
14
|
+
html
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_shortcode(tag, &block)
|
19
|
+
@shortcode_tags[tag] = block
|
20
|
+
end
|
21
|
+
|
22
|
+
def remove_shortcode(tag)
|
23
|
+
@shortcode_tags.delete tag
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_shortcode_regex
|
27
|
+
tagnames = @shortcode_tags.keys
|
28
|
+
tagregexp = tagnames.map{ |x| Regexp::quote(x) }.join('|')
|
29
|
+
|
30
|
+
Regexp.new('\[' + # Opening bracket
|
31
|
+
'(\[?)' + # 1: Optional second opening bracket for escaping shortcodes: [[tag]]
|
32
|
+
"(#{tagregexp})" + # 2: Shortcode name
|
33
|
+
'\b' + # Word boundary
|
34
|
+
'(' + # 3: Unroll the loop: Inside the opening shortcode tag
|
35
|
+
'[^\]\/]*' + # Not a closing bracket or forward slash
|
36
|
+
'(?:' +
|
37
|
+
'\/(?!\])' + # A forward slash not followed by a closing bracket
|
38
|
+
'[^\]\/]*' + # Not a closing bracket or forward slash
|
39
|
+
')*?' +
|
40
|
+
')' +
|
41
|
+
'(?:' +
|
42
|
+
'(\/)' + # 4: Self closing tag ...
|
43
|
+
'\]' + # ... and closing bracket
|
44
|
+
'|' +
|
45
|
+
'\]' + # Closing bracket
|
46
|
+
'(?:' +
|
47
|
+
'(' + # 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
|
48
|
+
'[^\[]*+' + # Not an opening bracket
|
49
|
+
'(?:' +
|
50
|
+
'\[(?!\/\2\])' + # An opening bracket not followed by the closing shortcode tag
|
51
|
+
'[^\[]*+' + # Not an opening bracket
|
52
|
+
')*+' +
|
53
|
+
')' +
|
54
|
+
'\[\/\2\]' + # Closing shortcode tag
|
55
|
+
')?' +
|
56
|
+
')' +
|
57
|
+
'(\]?)' # 6: Optional second closing brocket for escaping shortcodes: [[tag]]
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def do_shortcode_tag(*m)
|
62
|
+
# allow [[foo]] syntax for escaping a tag
|
63
|
+
return m[0][1..-2] if m[1] == '[' && m[6] == ']'
|
64
|
+
|
65
|
+
tag = m[2]
|
66
|
+
att = shortcode_parse_atts m[3]
|
67
|
+
|
68
|
+
if m[5].present?
|
69
|
+
# enclosing tag - extra parameter
|
70
|
+
m[1] + @shortcode_tags[tag].call(att, m[5], tag) + m[6]
|
71
|
+
else
|
72
|
+
# self-closing tag
|
73
|
+
m[1] + @shortcode_tags[tag].call(att, nil, tag) + m[6]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def shortcode_parse_atts(text)
|
78
|
+
pattern = /(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*'([^']*)'(?:\s|$)|(\w+)\s*=\s*([^\s'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/
|
79
|
+
text = text.gsub /[\u{00a0}\u{200b}]+/, ' '
|
80
|
+
|
81
|
+
att_hash = {}
|
82
|
+
att_array = []
|
83
|
+
text.scan(pattern) do |m1, m2, m3, m4, m5, m6, m7, m8|
|
84
|
+
if m1.present?
|
85
|
+
att_hash[m1.downcase] = m2
|
86
|
+
elsif m3.present?
|
87
|
+
att_hash[m3.downcase] = m4
|
88
|
+
elsif m5.present?
|
89
|
+
att_hash[m5] = m6
|
90
|
+
elsif m7.present?
|
91
|
+
att_array << m7
|
92
|
+
elsif m8.present?
|
93
|
+
att_array << m8
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
if !att_hash.empty?
|
98
|
+
att_hash
|
99
|
+
elsif !att_array.empty?
|
100
|
+
att_array
|
101
|
+
else
|
102
|
+
text.lstrip
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def strip_shortcodes(content)
|
107
|
+
if @shortcode_tags.any?
|
108
|
+
content.gsub(get_shortcode_regex){ strip_shortcode_tag *($~.to_a) }
|
109
|
+
else
|
110
|
+
content
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def strip_shortcode_tag(*m)
|
115
|
+
# allow [[foo]] syntax for escaping a tag
|
116
|
+
if m[1] == '[' && m[6] == ']'
|
117
|
+
m[0][1..-2]
|
118
|
+
else
|
119
|
+
m[1] + m[6]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'shortcodes/version'
|
5
|
+
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "ruby-shortcodes"
|
9
|
+
spec.version = Shortcodes::VERSION
|
10
|
+
spec.authors = ["David Lee"]
|
11
|
+
spec.email = ["david.lee@envato.com"]
|
12
|
+
spec.description = %q{implement stupid Wordpress shortcodes in ruby}
|
13
|
+
spec.summary = %q{implement stupid Wordpress shortcodes in ruby}
|
14
|
+
spec.homepage = ""
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency 'activesupport'
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
File without changes
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shortcodes'
|
3
|
+
|
4
|
+
describe Shortcodes::TutsShortcodes do
|
5
|
+
subject(:shortcodes) { Shortcodes::TutsShortcodes.new }
|
6
|
+
|
7
|
+
describe '[xml]' do
|
8
|
+
it 'returns an appropriate pre tag for xml' do
|
9
|
+
xml_shortcode = '
|
10
|
+
[xml]
|
11
|
+
<div class="class">
|
12
|
+
Some Text
|
13
|
+
</div>
|
14
|
+
[/xml]
|
15
|
+
'
|
16
|
+
expected = '
|
17
|
+
<pre class="brush: xml">
|
18
|
+
<div class="class">
|
19
|
+
Some Text
|
20
|
+
</div></pre>
|
21
|
+
'
|
22
|
+
shortcodes.process(xml_shortcode).should == expected
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '[sponsored_content]' do
|
27
|
+
it 'returns an appropriate div tag for sponsored content' do
|
28
|
+
shortcode = '
|
29
|
+
[sponsored_content]
|
30
|
+
<a href="http://www.filterforge.com/?psdtuts" onclick="javascript:_gaq.push([\'_trackEvent\',\'outbound-article\',\'www.filterforge.com\']);" sl-processed="1">Filter Forge</a>
|
31
|
+
[/sponsored_content]
|
32
|
+
'
|
33
|
+
expected = '<div class="sponsored-shortcode"><strong>Sponsored Content</strong><p>This content was commissioned by <a href="http://www.filterforge.com/?psdtuts" onclick="javascript:_gaq.push([\'_trackEvent\',\'outbound-article\',\'www.filterforge.com\']);" sl-processed="1">Filter Forge</a> and was written and/or edited by the Tuts+ team. Our aim with sponsored content is to publish relevant and objective tutorials, case studies, and inspirational interviews that offer genuine educational value to our readers and enable us to fund the creation of more useful content.</p></div>'
|
34
|
+
|
35
|
+
shortcodes.process(shortcode).strip.should == expected
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '[sourcecode]' do
|
40
|
+
it 'returns an appropriate pre tag for the given language attribute of sourcecode' do
|
41
|
+
bash_shortcode = '
|
42
|
+
[sourcecode language="php"]
|
43
|
+
some php code
|
44
|
+
[/sourcecode]
|
45
|
+
'
|
46
|
+
expected = '
|
47
|
+
<pre class="brush: php">
|
48
|
+
some php code</pre>
|
49
|
+
'
|
50
|
+
shortcodes.process(bash_shortcode).should == expected
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns an appropriate pre tag for the given lang attribute of sourcecode' do
|
54
|
+
bash_shortcode = '
|
55
|
+
[sourcecode lang="php"]
|
56
|
+
some php code
|
57
|
+
[/sourcecode]
|
58
|
+
'
|
59
|
+
expected = '
|
60
|
+
<pre class="brush: php">
|
61
|
+
some php code</pre>
|
62
|
+
'
|
63
|
+
shortcodes.process(bash_shortcode).should == expected
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'uses plain brush as its default syntax if language attribute is not given' do
|
67
|
+
bash_shortcode = '
|
68
|
+
[sourcecode]
|
69
|
+
some random code
|
70
|
+
[/sourcecode]
|
71
|
+
'
|
72
|
+
expected = '
|
73
|
+
<pre class="brush: plain">
|
74
|
+
some random code</pre>
|
75
|
+
'
|
76
|
+
shortcodes.process(bash_shortcode).should == expected
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'returns nothing for a content-less shortcode tag' do
|
80
|
+
shortcode = '[sourcecode language="php"]'
|
81
|
+
expected = ''
|
82
|
+
shortcodes.process(shortcode).should == expected
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '[code]' do
|
87
|
+
it 'behaves the same as sourcecode' do
|
88
|
+
bash_shortcode = '
|
89
|
+
[code language="php"]
|
90
|
+
some php code
|
91
|
+
[/code]
|
92
|
+
'
|
93
|
+
expected = '
|
94
|
+
<pre class="brush: php">
|
95
|
+
some php code</pre>
|
96
|
+
'
|
97
|
+
shortcodes.process(bash_shortcode).should == expected
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '[tip]' do
|
102
|
+
let(:source) { '[tip]In doing something for the first time, imagine that you have already
|
103
|
+
done it in the past.[/tip]' }
|
104
|
+
let(:expected) { '<div class="tip-shortcode">In doing something for the first time, imagine that you have already
|
105
|
+
done it in the past.</div>' }
|
106
|
+
|
107
|
+
it 'wraps the tip in a div (WTF)' do
|
108
|
+
shortcodes.process(source).should == expected
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when tip has no content' do
|
112
|
+
let(:source) { '[tip]' }
|
113
|
+
|
114
|
+
it 'returns nothing' do
|
115
|
+
shortcodes.process(source).should == ''
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '[polldaddy]' do
|
121
|
+
let(:source) { '[polldaddy id="3382283" title="Whee whoo haha"]' }
|
122
|
+
let(:expected) { '<script type="text/javascript" charset="utf-8" src="http://static.polldaddy.com/p/3382283.js"></script>'}
|
123
|
+
|
124
|
+
it 'produces a polldaddy script tag' do
|
125
|
+
shortcodes.process(source).should == expected
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '[audio]' do
|
130
|
+
|
131
|
+
context "when type not specified" do
|
132
|
+
let(:source) { '[audio http://hello.com]' }
|
133
|
+
let(:expected) { '<audio src="http://hello.com" />'}
|
134
|
+
|
135
|
+
it 'produces an audio tag' do
|
136
|
+
shortcodes.process(source).should == expected
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when audio is separated from the tag with a colon with no space" do
|
141
|
+
let(:source) { '[audio:http://hello.com]' }
|
142
|
+
let(:expected) { '<audio src="http://hello.com" />'}
|
143
|
+
|
144
|
+
it 'produces an audio tag' do
|
145
|
+
shortcodes.process(source).should == expected
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when audio is separated from the tag with a colon and whitespace" do
|
150
|
+
let(:source) { '[audio: http://hello.com]' }
|
151
|
+
let(:expected) { '<audio src="http://hello.com" />'}
|
152
|
+
|
153
|
+
it 'produces an audio tag' do
|
154
|
+
shortcodes.process(source).should == expected
|
155
|
+
end
|
156
|
+
|
157
|
+
context "and the URL contains whitespace" do
|
158
|
+
let(:source) { '[audio: http://how silly.com]' }
|
159
|
+
let(:expected) { '<audio src="http://how silly.com" />'}
|
160
|
+
|
161
|
+
it "retains the full path with the whitespace" do
|
162
|
+
shortcodes.process(source).should == expected
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "when type is specified as mp3" do
|
168
|
+
let(:source) { "[audio mp3='http://hello.com']" }
|
169
|
+
let(:expected) { %Q[<audio src="http://hello.com" type='audio/mpeg; codecs=\"mp3\"' />]}
|
170
|
+
|
171
|
+
it 'produces an audio tag w/ an mp3 codec' do
|
172
|
+
shortcodes.process(source).should == expected
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "when type is specified as ogg" do
|
177
|
+
let(:source) { "[audio ogg='http://hello.com']" }
|
178
|
+
let(:expected) { %Q[<audio src="http://hello.com" type='audio/ogg; codecs=\"vorbis\"' />]}
|
179
|
+
|
180
|
+
it 'produces an audio tag w/ an ogg codec' do
|
181
|
+
shortcodes.process(source).should == expected
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '[WP_UnityObject]' do
|
188
|
+
let(:source) { '[WP_UnityObject src="http://activetuts.s3.amazonaws.com/tuts/448_unity4/preview/WebPlayer.unity3d" width="600" height="450" /]' }
|
189
|
+
let(:expected) { %{<script src="http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js"></script><script async>$(function(){new UnityObject2().initPlugin($('.unity-player')[0], "http://activetuts.s3.amazonaws.com/tuts/448_unity4/preview/WebPlayer.unity3d");});</script><div class="unity-player" style="width:600px;height:450px"><div class="unity-player__missing"><a href="http://unity3d.com/webplayer/"><img alt="Unity Web Player. Install now!" src="http://webplayer.unity3d.com/installation/getunity.png" width="193" height="63" /></a></div></div>} }
|
190
|
+
|
191
|
+
it 'produces a unity object tag' do
|
192
|
+
shortcodes.process(source).should == expected
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '[caption]' do
|
197
|
+
context 'with valid image and caption' do
|
198
|
+
let(:image) { '<img src="http://localhost/wp-content/uploads/2010/07/800px-Great_Wave_off_Kanagawa2-300x205.jpg" alt="Kanagawa" title="The Great Wave" width="300" height="205" class="size-medium wp-image-6" />' }
|
199
|
+
let(:caption) { 'WordPress shortcodes always exist for a good reason' }
|
200
|
+
let(:source) { %([caption id="attachment_6" align="alignright" width="300"]#{image} #{caption}[/caption]) }
|
201
|
+
|
202
|
+
it 'wraps content in figure and figcaption tags' do
|
203
|
+
expect(shortcodes.process(source)).to eq %(<figure class="post_image">#{image}<figcaption>#{caption}</figcaption></figure>)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context 'with invalid content' do
|
208
|
+
let(:content) { 'All content is valid content' }
|
209
|
+
let(:source) { %([caption id="attachment_5" align="alignright" width="300"]#{content}[/caption]) }
|
210
|
+
|
211
|
+
it 'returns content' do
|
212
|
+
expect(shortcodes.process(source)).to eq content
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '[player]' do
|
218
|
+
let(:source) { '[player href="http://s3.amazonaws.com/nettuts/631_myows/apiRegister.flv" width="600" height="494"]' }
|
219
|
+
let(:expected) { %{<video class="post__content-video" src="http://s3.amazonaws.com/nettuts/631_myows/apiRegister.flv" width="600" height="494" />} }
|
220
|
+
|
221
|
+
# This relies on some html5 player being initialised for all <video> tags. In the case of Hub at the time of writing
|
222
|
+
# we already have mediaelement loaded for Courses videos, so this just works.
|
223
|
+
it 'produces a video tag' do
|
224
|
+
shortcodes.process(source).should == expected
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shortcodes'
|
3
|
+
|
4
|
+
describe Shortcodes::WordpressShortcodes do
|
5
|
+
subject(:shortcodes) { Shortcodes::WordpressShortcodes.new }
|
6
|
+
|
7
|
+
describe '#process' do
|
8
|
+
it 'executes a simple shortcode' do
|
9
|
+
shortcodes.add_shortcode('foo'){ 'foo!' }
|
10
|
+
shortcodes.process('A [foo]').should == 'A foo!'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'executes a wrapping shortcode and passes contents' do
|
14
|
+
shortcodes.add_shortcode('foo'){ |attr, content| "foo#{content}!" }
|
15
|
+
shortcodes.process('A [foo]bar[/foo] Totally').should == 'A foobar! Totally'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'executes a shortcode with attributes' do
|
19
|
+
shortcodes.add_shortcode('foo'){ |attr| "foo to the #{attr['adjective']}, #{attr['noun']}!"}
|
20
|
+
shortcodes.process('[foo noun="fox" adjective="owlish"]').should == 'foo to the owlish, fox!'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'executes a shortcode with attributes and content' do
|
24
|
+
shortcodes.add_shortcode('foo'){ |attr, content| "#{content} to the #{attr['adjective']}, #{attr['noun']}!"}
|
25
|
+
shortcodes.process('[foo noun="fox" adjective="owlish"]Greetings[/foo]').should == 'Greetings to the owlish, fox!'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'executes multiple shortcodes in a string' do
|
29
|
+
shortcodes.add_shortcode('banana'){ "Bananas, yum!" }
|
30
|
+
shortcodes.add_shortcode('pizza'){ "Pizza, yum!" }
|
31
|
+
shortcodes.process('[banana] [pizza] [banana]').should == 'Bananas, yum! Pizza, yum! Bananas, yum!'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-shortcodes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.18
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Lee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: implement stupid Wordpress shortcodes in ruby
|
70
|
+
email:
|
71
|
+
- david.lee@envato.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- lib/shortcodes.rb
|
83
|
+
- lib/shortcodes/tuts_shortcodes.rb
|
84
|
+
- lib/shortcodes/version.rb
|
85
|
+
- lib/shortcodes/wordpress_shortcodes.rb
|
86
|
+
- ruby-shortcodes.gemspec
|
87
|
+
- spec/spec_helper.rb
|
88
|
+
- spec/tuts_shortcodes_spec.rb
|
89
|
+
- spec/wordpress_shortcodes_spec.rb
|
90
|
+
homepage: ''
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.0.3
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: implement stupid Wordpress shortcodes in ruby
|
113
|
+
test_files:
|
114
|
+
- spec/spec_helper.rb
|
115
|
+
- spec/tuts_shortcodes_spec.rb
|
116
|
+
- spec/wordpress_shortcodes_spec.rb
|