texttube_baby 0.0.4
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.
- 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!}
|
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
|