texttube_baby 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +9 -0
- data/LICENCE.txt +22 -0
- data/README.md +242 -0
- data/Rakefile +2 -0
- data/lib/ext/blank.rb +21 -0
- data/lib/texttube/baby.rb +5 -0
- data/lib/texttube/baby/coderay.rb +68 -0
- data/lib/texttube/baby/embedding_audio.rb +62 -0
- data/lib/texttube/baby/embedding_video.rb +124 -0
- data/lib/texttube/baby/inside_block.rb +35 -0
- data/lib/texttube/baby/link_reffing.rb +147 -0
- data/lib/texttube/baby/spiffing.rb +44 -0
- data/lib/texttube/baby/version.rb +5 -0
- data/spec/coderay_spec.rb +86 -0
- data/spec/embedding_audio_spec.rb +41 -0
- data/spec/embedding_video_spec.rb +35 -0
- data/spec/inside_block_spec.rb +34 -0
- data/spec/link_reffing_spec.rb +100 -0
- data/spec/markdownfilters_spec.rb +279 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/spiffing_spec.rb +49 -0
- data/texttube_baby.gemspec +25 -0
- metadata +145 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require "texttube/filterable"
|
3
|
+
|
4
|
+
module TextTube
|
5
|
+
|
6
|
+
# Embed video via [embed_SIZE[url|description]]
|
7
|
+
module EmbeddingVideo
|
8
|
+
extend TextTube::Filterable
|
9
|
+
|
10
|
+
filter_with :embeddingvideo do |text|
|
11
|
+
run text
|
12
|
+
end
|
13
|
+
|
14
|
+
# List of available sites.
|
15
|
+
SITES = {
|
16
|
+
# "video.google".to_sym => ['http://www.video.google.com/',->(w,h,url){ %Q!! }],
|
17
|
+
# :brightcove => ['http://www.brightcove.com/',->(w,h,url){ %Q!! }],
|
18
|
+
# :photobucket => ['http://www.photobucket.com/',->(w,h,url){ %Q!! }],
|
19
|
+
:youtube => {
|
20
|
+
name: 'https://www.youtube.com/',
|
21
|
+
html: ->(w,h,url){ %Q!<iframe title="YouTube video player" class="youtube-player" type="text/html" width="#{w}" height="#{h}" src="#{url}" frameborder="0"></iframe>!.strip},
|
22
|
+
url_morph: ->(orig){
|
23
|
+
if orig.match %r{youtube\.com}
|
24
|
+
orig.sub( %r{watch\?v=}, 'embed/')
|
25
|
+
elsif orig.match %r{youtu\.be}
|
26
|
+
orig.sub( %r{youtu\.be}, "www.youtube.com/embed" )
|
27
|
+
else
|
28
|
+
fail ArgumentError, "That is not a youtube link"
|
29
|
+
end
|
30
|
+
}
|
31
|
+
},
|
32
|
+
# :dailymotion => ['http://dailymotion.com/',->(w,h,url){ %Q!! }],
|
33
|
+
# :ifilm => ['http://ifilm.com/',->(w,h,url){ %Q!! }],
|
34
|
+
# :break => ['http://break.com/',->(w,h,url){ %Q!! }],
|
35
|
+
# :blip => ['http://blip.tv/',->(w,h,url){ %Q!! }],
|
36
|
+
# :grindtv => ['http://www.grindtv.com/',->(w,h,url){ %Q!! }],
|
37
|
+
# :metacafe => ['http://metacafe.com/',->(w,h,url){ %Q!! }],
|
38
|
+
# :myspace => ['http://vids.myspace.com/',->(w,h,url){ %Q!! }],
|
39
|
+
# :vimeo => ['http://vimeo.com/',->(w,h,url){ %Q!! }],
|
40
|
+
# :buzznet => ['http://buzznet.com/',->(w,h,url){ %Q!! }],
|
41
|
+
# :liveleak => ['http://www.liveleak.com/',->(w,h,url){ %Q!! }],
|
42
|
+
# :stupidvideos => ['http://stupidvideos.com/',->(w,h,url){ %Q!! }],
|
43
|
+
# :flixya => ['http://www.flixya.com/',->(w,h,url){ %Q!! }],
|
44
|
+
# :gofish => ['http://gofish.com/',->(w,h,url){ %Q!! }],
|
45
|
+
# :kewego => ['http://kewego.com/',->(w,h,url){ %Q!! }],
|
46
|
+
# :lulu => ['http://lulu.tv/',->(w,h,url){ %Q!! }],
|
47
|
+
# :pandora => ['http://pandora.tv/',->(w,h,url){ %Q!! }],
|
48
|
+
# :viddler => ['http://www.viddler.com/',->(w,h,url){ %Q!! }],
|
49
|
+
# :myheavy => ['http://myheavy.com/',->(w,h,url){ %Q!! }],
|
50
|
+
# :putfile => ['http://putfile.com/',->(w,h,url){ %Q!! }],
|
51
|
+
# :stupidvideos => ['http://stupidvideos.com/',->(w,h,url){ %Q!! }],
|
52
|
+
# :vmix => ['http://vmix.com/',->(w,h,url){ %Q!! }],
|
53
|
+
# :zippyvideos => ['http://zippyvideos.com/',->(w,h,url){ %Q!! }],
|
54
|
+
# :castpost => ['http://castpost.com/',->(w,h,url){ %Q!! }],
|
55
|
+
# :dotv => ['http://dotv.com/',->(w,h,url){ %Q!! }],
|
56
|
+
# :famster => ['http://famster.com/',->(w,h,url){ %Q!! }],
|
57
|
+
# :gawkk => ['http://gawkk.com/',->(w,h,url){ %Q!! }],
|
58
|
+
# :tubetorial => ['http://tubetorial.com/',->(w,h,url){ %Q!! }],
|
59
|
+
# :MeraVideo => ['http://MeraVideo.com/',->(w,h,url){ %Q!! }],
|
60
|
+
# :Porkolt => ['http://Porkolt.com/',->(w,h,url){ %Q!! }],
|
61
|
+
# :VideoWebTown => ['http://VideoWebTown.com/',->(w,h,url){ %Q!! }],
|
62
|
+
# :Vidmax => ['http://Vidmax.com/',->(w,h,url){ %Q!! }],
|
63
|
+
# :clipmoon => ['http://www.clipmoon.com/',->(w,h,url){ %Q!! }],
|
64
|
+
# :motorsportmad => ['http://motorsportmad.com/',->(w,h,url){ %Q!! }],
|
65
|
+
# :thatshow => ['http://www.thatshow.com/',->(w,h,url){ %Q!! }],
|
66
|
+
# :clipchef => ['http://clipchef.com/',->(w,h,url){ %Q!! }],
|
67
|
+
}
|
68
|
+
|
69
|
+
# Some standard player sizes.
|
70
|
+
SIZES = {
|
71
|
+
small: {w: 560, h: 345},
|
72
|
+
medium: {w: 640, h:390},
|
73
|
+
large: {w: 853, h:510},
|
74
|
+
largest: {w: 1280, h:750},
|
75
|
+
}
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
# r_url = %r{
|
80
|
+
# http(?:s)?\:// #http https ://
|
81
|
+
# (?:(?:www|vids)\.)? # www. vids.
|
82
|
+
# (.+?) # domain name (hopefully)
|
83
|
+
# \.(?:com|tv) # .com .tv
|
84
|
+
# /? # optional trailing slash
|
85
|
+
# }x
|
86
|
+
|
87
|
+
# Pattern for deconstructing [video_SIZE[url|description]]
|
88
|
+
R_link = / # [video_SIZE[url|description]]
|
89
|
+
\[video # opening square brackets
|
90
|
+
(?:\_(?<size>[a-z]+))? # player size (optional)
|
91
|
+
\[
|
92
|
+
(?<url>[^\|]+) # url
|
93
|
+
\| # separator
|
94
|
+
(?<desc>[^\[]+) # description
|
95
|
+
\]\] # closing square brackets
|
96
|
+
/x
|
97
|
+
|
98
|
+
|
99
|
+
# @param [String] content
|
100
|
+
# @param [Hash] options
|
101
|
+
# @return [String]
|
102
|
+
def self.run(content, options={})
|
103
|
+
options ||= {}
|
104
|
+
content.gsub( R_link ) { |m|
|
105
|
+
|
106
|
+
size,url,desc = $1,$2,$3
|
107
|
+
|
108
|
+
res =
|
109
|
+
if size.nil?
|
110
|
+
SIZES[:medium]
|
111
|
+
else
|
112
|
+
SIZES[size.to_sym] || SIZES[:medium] #resolution
|
113
|
+
end
|
114
|
+
|
115
|
+
#"res: #{res.inspect} size: #{size}, url:#{url}, desc:#{desc}"
|
116
|
+
|
117
|
+
emb_url = SITES[:youtube][:url_morph].(url)
|
118
|
+
SITES[:youtube][:html].(res[:w], res[:h], emb_url )
|
119
|
+
}
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end # class
|
124
|
+
end # module
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'nokogiri'
|
3
|
+
require_relative "../filterable.rb"
|
4
|
+
|
5
|
+
module TextTube
|
6
|
+
|
7
|
+
# This finds html tags with "markdown='1'" as an attribute, runs markdown over the contents, then removes the markdown attribute, allowing markdown within html blocks
|
8
|
+
module InsideBlock
|
9
|
+
extend TextTube::Filterable
|
10
|
+
|
11
|
+
filter_with :insideblock do |text|
|
12
|
+
TextTube::InsideBlock.run text
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [String] content
|
16
|
+
# @param [Hash] options
|
17
|
+
# @option options [Constant] The markdown parser to use. I'm not sure this bit really works for other parsers than RDiscount.
|
18
|
+
def self.run( content, options={})
|
19
|
+
options ||= {}
|
20
|
+
if options[:markdown_parser].nil?
|
21
|
+
require 'rdiscount'
|
22
|
+
markdown_parser=RDiscount
|
23
|
+
end
|
24
|
+
doc = Nokogiri::HTML::fragment(content)
|
25
|
+
|
26
|
+
(doc/"*[@markdown='1']").each do |ele|
|
27
|
+
ele.inner_html = markdown_parser.new(ele.inner_html).to_html
|
28
|
+
ele.remove_attribute("markdown")
|
29
|
+
end
|
30
|
+
|
31
|
+
doc.to_s
|
32
|
+
end # run
|
33
|
+
|
34
|
+
end # class
|
35
|
+
end # module
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require "texttube/filterable.rb"
|
3
|
+
require_relative "../../ext/blank.rb"
|
4
|
+
|
5
|
+
module TextTube
|
6
|
+
module Baby
|
7
|
+
|
8
|
+
# @author Iain Barnett
|
9
|
+
# A class to take links in the format `[[link|description]]` and give them a number reference, then output them in markdown format. Note: this is not the same as reference links in markdown, this is more akin to the way books will refer to references or footnotes with a number.
|
10
|
+
#P.S. I don't like to make functions private, we're all adults, so to use this call Link_reffing#run, #format_links is for internal use.
|
11
|
+
module LinkReffing
|
12
|
+
extend Filterable
|
13
|
+
|
14
|
+
filter_with :linkreffing do |text, options|
|
15
|
+
run text, options
|
16
|
+
end
|
17
|
+
|
18
|
+
# These are the html codes for superscript 0 - 9
|
19
|
+
UNITS = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'] #unicode superscript numbers
|
20
|
+
|
21
|
+
# Matches [[link|description]]
|
22
|
+
Pattern = /
|
23
|
+
\[\[ # opening square brackets
|
24
|
+
(?<link>\S+)
|
25
|
+
\s*\|\s* # separator
|
26
|
+
(?<description>[^\[]+)
|
27
|
+
\]\] # closing square brackets
|
28
|
+
/x
|
29
|
+
|
30
|
+
# a lambda function to transform a link and a number into a markdown reference link.
|
31
|
+
# @param [String] lnk The url.
|
32
|
+
# @param [String] num The reference number.
|
33
|
+
Reffer = ->(lnk, num){ %Q![#{lnk}](##{num} "Jump to reference")!}
|
34
|
+
|
35
|
+
# A lambda to transform a link and a number to a HTML reference link.
|
36
|
+
RefHTMLer = ->(lnk, num){ %Q!<a href="##{num}" title="Jump to reference">#{lnk}</a>! }
|
37
|
+
|
38
|
+
# A lambda to transform a href and a description into an HTML link.
|
39
|
+
HTMLer = ->(lnk, desc){ %Q! <a href="#{lnk}">#{desc}</a>! }
|
40
|
+
|
41
|
+
# A lambda to transform a link and a description into an inline Markdown link.
|
42
|
+
Markdowner = ->(lnk, desc){ %Q! [#{desc}](#{lnk})! }
|
43
|
+
|
44
|
+
# Noner = ->(_,_) { "" } # this isn't needed but will sit here as a reminder.
|
45
|
+
|
46
|
+
|
47
|
+
# Takes markdown content with ref links and turns it into 100% markdown.
|
48
|
+
# @param [String] content The markdown content with links to ref.
|
49
|
+
# @option options [#to_s] :format The format of the link you want added. The options are :html, :markdown. The default is :markdown
|
50
|
+
# @option options [#to_s] :kind The kind of link you want added. The options are :reference, :inline, :none. The default is :reference
|
51
|
+
# @option options [String,nil] :div_id ID of the div to wrap reference links in. Defaults to "reflinks". Set to nil or false for no div.
|
52
|
+
# @return [String] The string formatted as markdown e.g. `[http://cheat.errtheblog.com/s/yard/more/and/m...](http://cheat.errtheblog.com/s/yard/more/and/more/and/more/ "http://cheat.errtheblog.com/s/yard/more/and/more/and/more/")`
|
53
|
+
def self.run(content, options={})
|
54
|
+
content = TextTube::String.new(content)
|
55
|
+
return content if content.blank?
|
56
|
+
text = content.dup
|
57
|
+
options ||= {}
|
58
|
+
kind = options.fetch :kind, :reference
|
59
|
+
format = options.fetch( :format, :markdown )
|
60
|
+
formatter = if kind == :inline
|
61
|
+
if format == :html
|
62
|
+
HTMLer
|
63
|
+
else
|
64
|
+
Markdowner
|
65
|
+
end
|
66
|
+
elsif kind == :none
|
67
|
+
nil # none is needed
|
68
|
+
else # kind == :reference
|
69
|
+
if format == :html
|
70
|
+
RefHTMLer
|
71
|
+
else
|
72
|
+
Reffer
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
div_id = options.has_key?(:div_id) ?
|
77
|
+
options[:div_id] :
|
78
|
+
:reflinks
|
79
|
+
|
80
|
+
cur = 0 #current number
|
81
|
+
|
82
|
+
# if there are no reflinks found
|
83
|
+
# this will remain false
|
84
|
+
# and `divit` won't be run.
|
85
|
+
has_reflinks = false
|
86
|
+
|
87
|
+
links = [] #to store the matches
|
88
|
+
|
89
|
+
text.gsub! Pattern do |md| #block to pass to gsub
|
90
|
+
has_reflinks = true
|
91
|
+
if kind == :inline
|
92
|
+
formatter.($1,$2)
|
93
|
+
elsif kind == :none
|
94
|
+
""
|
95
|
+
else # kind == :reference
|
96
|
+
mags = cur.divmod(10) #get magnitude of number
|
97
|
+
ref_tag = mags.first >= 1 ?
|
98
|
+
UNITS[mags.first] :
|
99
|
+
'' #sort out tens
|
100
|
+
|
101
|
+
ref_tag += UNITS[mags.last] #units
|
102
|
+
retval = formatter.(ref_tag,cur)
|
103
|
+
|
104
|
+
links << [$1, $2, cur] # add to the words list
|
105
|
+
cur += 1 #increase current number
|
106
|
+
retval
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if !links.empty?
|
111
|
+
if has_reflinks && div_id
|
112
|
+
"#{text}\n#{LinkReffing.divit( div_id ) { format_links(links) }}"
|
113
|
+
else
|
114
|
+
"#{text}\n#{format_links(links)}"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
text
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# This func outputs the link as valid markdown.
|
123
|
+
# @param [Array<String,String,Integer>] links A list of 2-length arrays containing the url and the description and the reference number.
|
124
|
+
def self.format_links( links )
|
125
|
+
links.map{ |(link, description, cur)|
|
126
|
+
display_link = link.length >= 45 ?
|
127
|
+
link[0,45] + "..." :
|
128
|
+
link
|
129
|
+
%Q!\n<a name="#{cur}"></a>#{LeftSq}#{cur}#{RightSq} [#{display_link}](#{link} "#{link}") #{description}\n\n!
|
130
|
+
}.join
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
# Wraps things in a div. If no id given, no div.
|
135
|
+
# @param [#to_s] id The ID attribute for the div.
|
136
|
+
def self.divit( id )
|
137
|
+
"<div markdown='1' id='#{id}'>#{ yield }</div>"
|
138
|
+
end
|
139
|
+
|
140
|
+
# HTML code for [
|
141
|
+
LeftSq = "["
|
142
|
+
# HTML code for ]
|
143
|
+
RightSq = "]"
|
144
|
+
|
145
|
+
end#class
|
146
|
+
end
|
147
|
+
end#module
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require "texttube/filterable"
|
3
|
+
|
4
|
+
module TextTube
|
5
|
+
module Baby
|
6
|
+
|
7
|
+
# Will transform the Queen's English into American English for use in CSS, as the current CSS standards prefer ugly words.
|
8
|
+
# Inspired by visualidiot's SpiffingCSS (see http://spiffingcss.com/)
|
9
|
+
module Spiffing
|
10
|
+
extend TextTube::Filterable
|
11
|
+
|
12
|
+
filter_with :spiffing do |text|
|
13
|
+
run text
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# The dictionary.
|
18
|
+
DICTIONARY = {
|
19
|
+
# Queen's English # Primitive English from our stateside
|
20
|
+
# friends from across the pond.
|
21
|
+
'colour' => 'color',
|
22
|
+
'grey' => 'gray',
|
23
|
+
'!please' => '!important',
|
24
|
+
'transparency' => 'opacity',
|
25
|
+
'centre' => 'center',
|
26
|
+
'plump' => 'bold',
|
27
|
+
'photograph' => 'image',
|
28
|
+
'capitalise' => 'capitalize'
|
29
|
+
}
|
30
|
+
|
31
|
+
# @param [String] content
|
32
|
+
# @param [Hash] options
|
33
|
+
def self.run( content, options={})
|
34
|
+
ugly_child = content.dup
|
35
|
+
# warn ugly_child
|
36
|
+
DICTIONARY.each do |english, ugly|
|
37
|
+
ugly_child.sub! english, ugly
|
38
|
+
# warn ugly_child
|
39
|
+
end
|
40
|
+
ugly_child
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative "../lib/texttube/baby/coderay.rb"
|
5
|
+
|
6
|
+
module TextTube
|
7
|
+
describe TextTube do
|
8
|
+
|
9
|
+
let(:coderayed){
|
10
|
+
%Q!<h2>Hello</h2>\n\n<p>This is some code:</p>\n\n<pre><code class="CodeRay">[<span class="integer">1</span>,<span class="integer">2</span>,<span class="integer">3</span>].map{|x| + <span class="integer">1</span> }\n</code></pre>\n\n<p>And this is the result:\n [2,3,4]</p>\n\n<p>Thankyou</p>\n!
|
11
|
+
}
|
12
|
+
|
13
|
+
let(:notrayed) {
|
14
|
+
"<h2>Hello</h2>\n\n<p>This is some code:</p>\n\n<pre><code>[1,2,3].map{|x| + 1 }\n</code></pre>\n\n<p>And this is the result:\n [2,3,4]</p>\n\n<p>Thankyou</p>\n"
|
15
|
+
}
|
16
|
+
|
17
|
+
describe Coderay do
|
18
|
+
context "Given some text" do
|
19
|
+
context "With some code to be rayed in it" do
|
20
|
+
context "That has a language hint" do
|
21
|
+
let(:content) { <<CODE
|
22
|
+
<pre><code>::::ruby
|
23
|
+
{"one" => 1 }
|
24
|
+
</code></pre>
|
25
|
+
CODE
|
26
|
+
}
|
27
|
+
let(:expected) { <<HTML
|
28
|
+
<pre><code class="CodeRay">{<span class="string"><span class="delimiter">"</span><span class="content">one</span><span class="delimiter">"</span></span> => <span class="integer">1</span> }</code></pre>
|
29
|
+
HTML
|
30
|
+
}
|
31
|
+
let(:wrong) { <<CODE
|
32
|
+
<pre><code>::::json
|
33
|
+
{"one" => 1 }
|
34
|
+
</code></pre>
|
35
|
+
CODE
|
36
|
+
}
|
37
|
+
|
38
|
+
subject { TextTube::Coderay.run content }
|
39
|
+
it { should_not be_nil }
|
40
|
+
it { should == expected }
|
41
|
+
it { should_not == TextTube::Coderay.run(wrong) }
|
42
|
+
end
|
43
|
+
context "That has no language hint" do
|
44
|
+
let(:content) { notrayed }
|
45
|
+
let(:expected) { coderayed }
|
46
|
+
|
47
|
+
subject { TextTube::Coderay.run content }
|
48
|
+
it { should_not be_nil }
|
49
|
+
it { should == expected }
|
50
|
+
end
|
51
|
+
context "That has a 'skip' language hint" do
|
52
|
+
let(:content) { <<CODE
|
53
|
+
<pre><code>::::skip
|
54
|
+
{"one" => 1 }
|
55
|
+
</code></pre>
|
56
|
+
CODE
|
57
|
+
}
|
58
|
+
let(:expected) { <<CODE
|
59
|
+
<pre><code>{"one" => 1 }</code></pre>
|
60
|
+
CODE
|
61
|
+
}
|
62
|
+
|
63
|
+
subject { TextTube::Coderay.run content }
|
64
|
+
it { should_not be_nil }
|
65
|
+
it { should == expected }
|
66
|
+
end
|
67
|
+
end # context
|
68
|
+
|
69
|
+
context "With no code to be rayed in it" do
|
70
|
+
let(:content) { %Q$The[UtterFAIL website](http://utterfail.info/ "UtterFAIL!") is good.$ }
|
71
|
+
let(:expected) { content }
|
72
|
+
subject { TextTube::Coderay.run content }
|
73
|
+
it { should_not be_nil }
|
74
|
+
it { should == expected }
|
75
|
+
end # context
|
76
|
+
end # context
|
77
|
+
|
78
|
+
context "Given no text" do
|
79
|
+
subject { TextTube::Coderay.run "" }
|
80
|
+
it { should_not be_nil }
|
81
|
+
it { should == "" }
|
82
|
+
end # context
|
83
|
+
|
84
|
+
end # describe Coderay
|
85
|
+
end # describe TextTube
|
86
|
+
end # module
|