random-words 1.0.4 → 1.0.6
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 +4 -4
- data/.rspec_status +148 -39
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +42 -0
- data/Gemfile.lock +4 -1
- data/README.md +153 -4
- data/bin/randw +195 -49
- data/lib/random-words/array.rb +51 -0
- data/lib/random-words/config.rb +248 -0
- data/lib/random-words/generator.rb +239 -93
- data/lib/random-words/hash.rb +16 -0
- data/lib/random-words/html2markdown.rb +205 -0
- data/lib/random-words/lorem-markdown.rb +398 -0
- data/lib/random-words/number-to-word.rb +137 -0
- data/lib/random-words/source.rb +105 -0
- data/lib/random-words/string.rb +221 -47
- data/lib/random-words/table-cleanup.rb +210 -0
- data/lib/random-words/version.rb +1 -1
- data/lib/random-words/words/1984/adjectives.txt +103 -0
- data/lib/random-words/words/1984/adverbs.txt +92 -0
- data/lib/random-words/words/1984/articles-plural.txt +10 -0
- data/lib/random-words/words/1984/articles-singular.txt +10 -0
- data/lib/random-words/words/1984/clauses.txt +79 -0
- data/lib/random-words/words/1984/config.yml +4 -0
- data/lib/random-words/words/1984/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/1984/conjunctions-subordinate.txt +29 -0
- data/lib/random-words/words/1984/names.txt +74 -0
- data/lib/random-words/words/1984/nouns-plural.txt +89 -0
- data/lib/random-words/words/1984/nouns-singular.txt +74 -0
- data/lib/random-words/words/1984/numbers.yml +5 -0
- data/lib/random-words/words/1984/prepositions.txt +89 -0
- data/lib/random-words/words/1984/terminators.txt +16 -0
- data/lib/random-words/words/1984/verbs-passive.txt +83 -0
- data/lib/random-words/words/1984/verbs-plural.txt +91 -0
- data/lib/random-words/words/1984/verbs-singular.txt +110 -0
- data/lib/random-words/words/alice/adjectives.txt +80 -0
- data/lib/random-words/words/alice/adverbs.txt +87 -0
- data/lib/random-words/words/alice/articles-plural.txt +10 -0
- data/lib/random-words/words/alice/articles-singular.txt +10 -0
- data/lib/random-words/words/alice/clauses.txt +81 -0
- data/lib/random-words/words/alice/config.yml +4 -0
- data/lib/random-words/words/alice/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/alice/conjunctions-subordinate.txt +29 -0
- data/lib/random-words/words/alice/names.txt +74 -0
- data/lib/random-words/words/alice/nouns-plural.txt +95 -0
- data/lib/random-words/words/alice/nouns-singular.txt +82 -0
- data/lib/random-words/words/alice/numbers.yml +5 -0
- data/lib/random-words/words/alice/prepositions.txt +45 -0
- data/lib/random-words/words/alice/terminators.txt +16 -0
- data/lib/random-words/words/alice/verbs-passive.txt +495 -0
- data/lib/random-words/words/alice/verbs-plural.txt +115 -0
- data/lib/random-words/words/alice/verbs-singular.txt +97 -0
- data/lib/random-words/words/bacon/clauses.txt +592 -592
- data/lib/random-words/words/bacon/config.yml +4 -0
- data/lib/random-words/words/bacon/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/bacon/names.txt +74 -0
- data/lib/random-words/words/bacon/numbers.yml +5 -0
- data/lib/random-words/words/bacon/prepositions.txt +45 -0
- data/lib/random-words/words/bacon/terminators.txt +16 -0
- data/lib/random-words/words/corporate/config.yml +4 -0
- data/lib/random-words/words/corporate/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/corporate/names.txt +74 -0
- data/lib/random-words/words/corporate/numbers.yml +5 -0
- data/lib/random-words/words/corporate/prepositions.txt +45 -0
- data/lib/random-words/words/corporate/terminators.txt +16 -0
- data/lib/random-words/words/doctor/adjectives.txt +92 -0
- data/lib/random-words/words/doctor/adverbs.txt +92 -0
- data/lib/random-words/words/doctor/articles-plural.txt +10 -0
- data/lib/random-words/words/doctor/articles-singular.txt +10 -0
- data/lib/random-words/words/doctor/clauses.txt +83 -0
- data/lib/random-words/words/doctor/config.yml +10 -0
- data/lib/random-words/words/doctor/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/doctor/conjunctions-subordinate.txt +29 -0
- data/lib/random-words/words/doctor/names.txt +74 -0
- data/lib/random-words/words/doctor/nouns-plural.txt +84 -0
- data/lib/random-words/words/doctor/nouns-singular.txt +84 -0
- data/lib/random-words/words/doctor/numbers.yml +5 -0
- data/lib/random-words/words/doctor/prepositions.txt +45 -0
- data/lib/random-words/words/doctor/terminators.txt +16 -0
- data/lib/random-words/words/doctor/verbs-passive.txt +83 -0
- data/lib/random-words/words/doctor/verbs-plural.txt +88 -0
- data/lib/random-words/words/doctor/verbs-singular.txt +83 -0
- data/lib/random-words/words/english/clauses.txt +592 -592
- data/lib/random-words/words/english/config.yml +4 -0
- data/lib/random-words/words/english/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/english/names.txt +74 -0
- data/lib/random-words/words/english/numbers.yml +5 -0
- data/lib/random-words/words/english/prepositions.txt +45 -0
- data/lib/random-words/words/english/terminators.txt +16 -0
- data/lib/random-words/words/english/verbs-plural.txt +1 -0
- data/lib/random-words/words/english/verbs-singular.txt +1 -0
- data/lib/random-words/words/foulmouth/adjectives.txt +89 -0
- data/lib/random-words/words/foulmouth/adverbs.txt +97 -0
- data/lib/random-words/words/foulmouth/articles-plural.txt +10 -0
- data/lib/random-words/words/foulmouth/articles-singular.txt +10 -0
- data/lib/random-words/words/foulmouth/clauses.txt +74 -0
- data/lib/random-words/words/foulmouth/config.yml +4 -0
- data/lib/random-words/words/foulmouth/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/foulmouth/conjunctions-subordinate.txt +29 -0
- data/lib/random-words/words/foulmouth/names.txt +74 -0
- data/lib/random-words/words/foulmouth/nouns-plural.txt +96 -0
- data/lib/random-words/words/foulmouth/nouns-singular.txt +99 -0
- data/lib/random-words/words/foulmouth/numbers.yml +5 -0
- data/lib/random-words/words/foulmouth/prepositions.txt +35 -0
- data/lib/random-words/words/foulmouth/terminators.txt +16 -0
- data/lib/random-words/words/foulmouth/verbs-passive.txt +143 -0
- data/lib/random-words/words/foulmouth/verbs-plural.txt +91 -0
- data/lib/random-words/words/foulmouth/verbs-singular.txt +104 -0
- data/lib/random-words/words/hipster/adjectives.txt +100 -0
- data/lib/random-words/words/hipster/adverbs.txt +89 -0
- data/lib/random-words/words/hipster/articles-plural.txt +10 -0
- data/lib/random-words/words/hipster/articles-singular.txt +10 -0
- data/lib/random-words/words/hipster/clauses.txt +180 -0
- data/lib/random-words/words/hipster/config.yml +4 -0
- data/lib/random-words/words/hipster/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/hipster/conjunctions-subordinate.txt +29 -0
- data/lib/random-words/words/hipster/names.txt +74 -0
- data/lib/random-words/words/hipster/nouns-plural.txt +96 -0
- data/lib/random-words/words/hipster/nouns-singular.txt +100 -0
- data/lib/random-words/words/hipster/numbers.yml +5 -0
- data/lib/random-words/words/hipster/prepositions.txt +45 -0
- data/lib/random-words/words/hipster/terminators.txt +16 -0
- data/lib/random-words/words/hipster/verbs-passive.txt +88 -0
- data/lib/random-words/words/hipster/verbs-plural.txt +106 -0
- data/lib/random-words/words/hipster/verbs-singular.txt +114 -0
- data/lib/random-words/words/latin/config.yml +4 -0
- data/lib/random-words/words/latin/conjunctions-coordinating.txt +15 -0
- data/lib/random-words/words/latin/names.txt +74 -0
- data/lib/random-words/words/latin/numbers.yml +5 -0
- data/lib/random-words/words/latin/prepositions.txt +18 -0
- data/lib/random-words/words/latin/terminators.txt +16 -0
- data/lib/random-words/words/spanish/adjectives.txt +81 -0
- data/lib/random-words/words/spanish/adverbs.txt +87 -0
- data/lib/random-words/words/spanish/articles-plural.txt +4 -0
- data/lib/random-words/words/spanish/articles-singular.txt +4 -0
- data/lib/random-words/words/spanish/clauses.txt +74 -0
- data/lib/random-words/words/spanish/config.yml +4 -0
- data/lib/random-words/words/spanish/conjunctions-coordinating.txt +8 -0
- data/lib/random-words/words/spanish/conjunctions-subordinate.txt +16 -0
- data/lib/random-words/words/spanish/names.txt +74 -0
- data/lib/random-words/words/spanish/nouns-plural.txt +92 -0
- data/lib/random-words/words/spanish/nouns-singular.txt +125 -0
- data/lib/random-words/words/spanish/numbers.yml +5 -0
- data/lib/random-words/words/spanish/prepositions.txt +31 -0
- data/lib/random-words/words/spanish/terminators.txt +17 -0
- data/lib/random-words/words/spanish/verbs-passive.txt +495 -0
- data/lib/random-words/words/spanish/verbs-plural.txt +326 -0
- data/lib/random-words/words/spanish/verbs-singular.txt +351 -0
- data/lib/random-words/words/veggie/adjectives.txt +111 -0
- data/lib/random-words/words/veggie/adverbs.txt +81 -0
- data/lib/random-words/words/veggie/articles-plural.txt +10 -0
- data/lib/random-words/words/veggie/articles-singular.txt +10 -0
- data/lib/random-words/words/veggie/clauses.txt +57 -0
- data/lib/random-words/words/veggie/config.yml +4 -0
- data/lib/random-words/words/veggie/conjunctions-coordinating.txt +20 -0
- data/lib/random-words/words/veggie/conjunctions-subordinate.txt +29 -0
- data/lib/random-words/words/veggie/names.txt +74 -0
- data/lib/random-words/words/veggie/nouns-plural.txt +78 -0
- data/lib/random-words/words/veggie/nouns-singular.txt +105 -0
- data/lib/random-words/words/veggie/numbers.yml +5 -0
- data/lib/random-words/words/veggie/prepositions.txt +45 -0
- data/lib/random-words/words/veggie/terminators.txt +16 -0
- data/lib/random-words/words/veggie/verbs-passive.txt +56 -0
- data/lib/random-words/words/veggie/verbs-plural.txt +79 -0
- data/lib/random-words/words/veggie/verbs-singular.txt +79 -0
- data/lib/random-words.rb +28 -0
- data/random-words.gemspec +3 -1
- data/src/_README.md +153 -4
- metadata +168 -7
- data/lib/random-words/words/bacon/numbers.txt +0 -21
- data/lib/random-words/words/corporate/numbers.txt +0 -21
- data/lib/random-words/words/english/numbers.txt +0 -21
- data/lib/random-words/words/latin/numbers.txt +0 -21
@@ -0,0 +1,205 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'nokogiri'
|
5
|
+
require_relative 'table-cleanup'
|
6
|
+
|
7
|
+
module RandomWords
|
8
|
+
# Convert HTML to Markdown
|
9
|
+
class HTML2Markdown
|
10
|
+
attr_reader :markdown
|
11
|
+
|
12
|
+
# Initialize the HTML2Markdown converter
|
13
|
+
# @param str [String] The HTML string to convert
|
14
|
+
# @param baseurl [String] The base URL for resolving relative links
|
15
|
+
def initialize(str, baseurl = nil)
|
16
|
+
@links = []
|
17
|
+
@baseuri = (baseurl ? URI.parse(baseurl) : nil)
|
18
|
+
@section_level = 0
|
19
|
+
@encoding = str.encoding
|
20
|
+
@markdown = output_for(Nokogiri::HTML(str, baseurl).root).gsub(/\n\n\n+/, "\n\n\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
# Convert the HTML to Markdown
|
24
|
+
# @return [String] The converted Markdown string
|
25
|
+
# @example
|
26
|
+
# converter = HTML2Markdown.new('<p>Hello world</p>')
|
27
|
+
# puts converter.to_s
|
28
|
+
def to_s
|
29
|
+
i = 0
|
30
|
+
@markdown = TableCleanup.new(@markdown).clean
|
31
|
+
"#{@markdown}\n\n" + @links.map { |link|
|
32
|
+
i += 1
|
33
|
+
"[#{i}]: #{link[:href]}" + (link[:title] ? %( "#{link[:title]}") : '')
|
34
|
+
}.join("\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Recursively convert child nodes
|
38
|
+
# @param node [Nokogiri::XML::Node] The parent node
|
39
|
+
def output_for_children(node)
|
40
|
+
node.children.map do |el|
|
41
|
+
output_for(el)
|
42
|
+
end.join
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add a link to the list of links
|
46
|
+
# @param link [Hash] The link to add
|
47
|
+
def add_link(link)
|
48
|
+
if @baseuri
|
49
|
+
begin
|
50
|
+
link[:href] = URI.parse(link[:href])
|
51
|
+
rescue Exception
|
52
|
+
link[:href] = URI.parse('')
|
53
|
+
end
|
54
|
+
link[:href].scheme = @baseuri.scheme unless link[:href].scheme
|
55
|
+
unless link[:href].opaque
|
56
|
+
link[:href].host = @baseuri.host unless link[:href].host
|
57
|
+
link[:href].path = @baseuri.path.to_s + '/' + link[:href].path.to_s if link[:href].path.to_s[0] != '/'
|
58
|
+
end
|
59
|
+
link[:href] = link[:href].to_s
|
60
|
+
end
|
61
|
+
@links.each_with_index do |l, i|
|
62
|
+
return i + 1 if l[:href] == link[:href]
|
63
|
+
end
|
64
|
+
@links << link
|
65
|
+
@links.length
|
66
|
+
end
|
67
|
+
|
68
|
+
# Wrap a string to 74 characters
|
69
|
+
# @param str [String] The string to wrap
|
70
|
+
# @return [String] The wrapped string
|
71
|
+
def wrap(str)
|
72
|
+
return str if str =~ /\n/
|
73
|
+
|
74
|
+
out = []
|
75
|
+
line = []
|
76
|
+
str.split(/[ \t]+/).each do |word|
|
77
|
+
line << word
|
78
|
+
if line.join(' ').length >= 74
|
79
|
+
out << line.join(' ')
|
80
|
+
line = []
|
81
|
+
end
|
82
|
+
end
|
83
|
+
out << line.join(' ') + (str[-1..-1] =~ /[ \t\n]/ ? str[-1..-1] : '')
|
84
|
+
out.join("\n")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Convert a node to Markdown
|
88
|
+
# @param node [Nokogiri::XML::Node] The node to convert
|
89
|
+
# @return [String] The converted Markdown string
|
90
|
+
def output_for(node)
|
91
|
+
case node.name
|
92
|
+
when 'head', 'style', 'script'
|
93
|
+
''
|
94
|
+
when 'br'
|
95
|
+
" \n"
|
96
|
+
when 'p', 'div'
|
97
|
+
"\n\n#{output_for_children(node)}\n\n"
|
98
|
+
when 'section', 'article'
|
99
|
+
@section_level += 1
|
100
|
+
o = "\n\n----\n\n#{output_for_children(node)}\n\n"
|
101
|
+
@section_level -= 1
|
102
|
+
o
|
103
|
+
when /h(\d+)/
|
104
|
+
"\n\n" + ('#' * (::Regexp.last_match(1).to_i + @section_level) + ' ' + output_for_children(node)) + "\n\n"
|
105
|
+
when /mark/
|
106
|
+
"==#{output_for_children(node)}=="
|
107
|
+
when 'blockquote'
|
108
|
+
@section_level += 1
|
109
|
+
o = "\n\n> #{output_for_children(node).lstrip.gsub(/\n/, "\n> ")}\n\n".gsub(/> \n(> \n)+/, "> \n")
|
110
|
+
@section_level -= 1
|
111
|
+
o
|
112
|
+
when 'cite'
|
113
|
+
"*#{output_for_children(node)}*"
|
114
|
+
when 'ul'
|
115
|
+
"\n\n" + node.children.map { |el|
|
116
|
+
next if el.name == 'text'
|
117
|
+
|
118
|
+
"* #{output_for_children(el).gsub(/^(\t)|( )/, "\t\t").gsub(/^>/, "\t>")}\n"
|
119
|
+
}.join + "\n\n"
|
120
|
+
when 'ol'
|
121
|
+
i = 0
|
122
|
+
"\n\n" + node.children.map { |el|
|
123
|
+
next if el.name == 'text'
|
124
|
+
|
125
|
+
i += 1
|
126
|
+
"#{i}. #{output_for_children(el).gsub(/^(\t)|( )/, "\t\t").gsub(/^>/, "\t>")}\n"
|
127
|
+
}.join + "\n\n"
|
128
|
+
when 'code'
|
129
|
+
if @in_pre
|
130
|
+
@in_pre = false
|
131
|
+
node.text.strip
|
132
|
+
else
|
133
|
+
"`#{output_for_children(node).gsub(/\n/, ' ')}`"
|
134
|
+
end
|
135
|
+
when 'pre'
|
136
|
+
@in_pre = true
|
137
|
+
lang = node['lang'] || node['language']
|
138
|
+
lang = '' if lang.nil? || lang.empty?
|
139
|
+
"\n\n```#{lang}\n" + output_for_children(node).lstrip + "\n```\n\n"
|
140
|
+
when 'hr'
|
141
|
+
"\n\n----\n\n"
|
142
|
+
when 'a', 'link'
|
143
|
+
link = { href: node['href'], title: node['title'] }
|
144
|
+
"[#{output_for_children(node).gsub("\n", ' ')}][#{add_link(link)}]"
|
145
|
+
when 'img'
|
146
|
+
link = { href: node['src'], title: node['title'] }
|
147
|
+
"![#{node['alt']}][#{add_link(link)}]"
|
148
|
+
when 'video', 'audio', 'embed'
|
149
|
+
link = { href: node['src'], title: node['title'] }
|
150
|
+
"[#{output_for_children(node).gsub("\n", ' ')}][#{add_link(link)}]"
|
151
|
+
when 'object'
|
152
|
+
link = { href: node['data'], title: node['title'] }
|
153
|
+
"[#{output_for_children(node).gsub("\n", ' ')}][#{add_link(link)}]"
|
154
|
+
when 'i', 'em', 'u'
|
155
|
+
"_#{output_for_children(node)}_"
|
156
|
+
when 'b', 'strong'
|
157
|
+
"**#{output_for_children(node)}**"
|
158
|
+
when 'dl'
|
159
|
+
"\n\n" + node.children.map do |el|
|
160
|
+
case el.name
|
161
|
+
when 'dt'
|
162
|
+
"#{output_for_children(el)}\n"
|
163
|
+
when 'dd'
|
164
|
+
": #{output_for_children(el)}\n\n"
|
165
|
+
end
|
166
|
+
end.join + "\n\n"
|
167
|
+
# Tables are not part of Markdown, so we output WikiCreole
|
168
|
+
when 'table'
|
169
|
+
@table_header = true
|
170
|
+
node.children.select do |c|
|
171
|
+
%w[tr tbody thead].include?(c.name)
|
172
|
+
end.map do |c|
|
173
|
+
output_for(c)
|
174
|
+
end.join
|
175
|
+
when 'tr'
|
176
|
+
header = "\n"
|
177
|
+
if @table_header
|
178
|
+
@table_header = false
|
179
|
+
cells = node.children.select do |c|
|
180
|
+
%w[th td].include?(c.name)
|
181
|
+
end.count
|
182
|
+
header = "\n|#{cells.times.map { '-------' }.join('|')}|\n"
|
183
|
+
end
|
184
|
+
node.children.select do |c|
|
185
|
+
%w[th td].include?(c.name)
|
186
|
+
end.map do |c|
|
187
|
+
output_for(c)
|
188
|
+
end.join.gsub(/\|\|/, '|') + header
|
189
|
+
when 'th', 'td'
|
190
|
+
"| #{output_for_children(node)} |"
|
191
|
+
when 'text'
|
192
|
+
# Sometimes Nokogiri lies. Force the encoding back to what we know it is
|
193
|
+
if (c = node.content.force_encoding(@encoding)) =~ /\S/
|
194
|
+
c.gsub!(/\n\n+/, '<$PreserveDouble$>')
|
195
|
+
c.gsub!(/\s+/, ' ')
|
196
|
+
c.gsub(/<\$PreserveDouble\$>/, "\n\n")
|
197
|
+
else
|
198
|
+
c
|
199
|
+
end
|
200
|
+
else
|
201
|
+
output_for_children(node)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,398 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RandomWords
|
4
|
+
# Generates random Lorem Ipsum text in Markdown format.
|
5
|
+
class LoremMarkdown
|
6
|
+
# Stores the output
|
7
|
+
attr_accessor :output
|
8
|
+
|
9
|
+
# Stores the RandomWords::Generator
|
10
|
+
attr_accessor :generator
|
11
|
+
|
12
|
+
# Generates random Lorem Ipsum text.
|
13
|
+
# @param options [Hash] Options for generating Lorem Ipsum text.
|
14
|
+
# @return [String] A string of random Lorem Ipsum text.
|
15
|
+
def initialize(options = {})
|
16
|
+
@added = {
|
17
|
+
em: false,
|
18
|
+
strong: false,
|
19
|
+
link: false,
|
20
|
+
code: false,
|
21
|
+
mark: false
|
22
|
+
}
|
23
|
+
|
24
|
+
defaults = {
|
25
|
+
source: :latin,
|
26
|
+
grafs: 10,
|
27
|
+
sentences: 5,
|
28
|
+
length: :medium,
|
29
|
+
decorate: true,
|
30
|
+
link: false,
|
31
|
+
ul: false,
|
32
|
+
ol: false,
|
33
|
+
dl: false,
|
34
|
+
bq: false,
|
35
|
+
code: false,
|
36
|
+
mark: false,
|
37
|
+
headers: false,
|
38
|
+
table: false
|
39
|
+
}
|
40
|
+
|
41
|
+
@options = defaults.merge(options)
|
42
|
+
|
43
|
+
@generator = RandomWords::Generator.new(@options[:source], {
|
44
|
+
sentence_length: @options[:length],
|
45
|
+
paragraph_length: @options[:sentences]
|
46
|
+
})
|
47
|
+
|
48
|
+
@output = ''
|
49
|
+
strong = @options[:decorate]
|
50
|
+
em = @options[:decorate]
|
51
|
+
links = @options[:link]
|
52
|
+
code = @options[:code]
|
53
|
+
mark = @options[:mark]
|
54
|
+
force = []
|
55
|
+
# Generate the specified number of paragraphs.
|
56
|
+
@options[:grafs].times.with_index do |_, i|
|
57
|
+
@output += paragraph(1, em: em, strong: strong, links: links, code: code, mark: mark, force: force)
|
58
|
+
em = Random.rand(0..3).zero? && @options[:decorate]
|
59
|
+
strong = Random.rand(0..3).zero? && @options[:decorate]
|
60
|
+
links = Random.rand(0..3).zero? && @options[:link]
|
61
|
+
code = Random.rand(0..3).zero? && @options[:code]
|
62
|
+
|
63
|
+
if i == @options[:grafs] - 2
|
64
|
+
force << :code if !@added[:code] && @options[:code]
|
65
|
+
force << :link if !@added[:link] && @options[:link]
|
66
|
+
force << :em if !@added[:em] && @options[:decorate]
|
67
|
+
force << :strong if !@added[:strong] && @options[:decorate]
|
68
|
+
end
|
69
|
+
@output += "\n\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
generate
|
73
|
+
end
|
74
|
+
|
75
|
+
# Use the RandomWords class to generate the Lorem Ipsum text.
|
76
|
+
def generate
|
77
|
+
compress_newlines
|
78
|
+
|
79
|
+
items = { short: 4, medium: 8, long: 10, very_long: 12 }[@options[:length]]
|
80
|
+
|
81
|
+
if @options[:ul] && @options[:ol]
|
82
|
+
# If both unordered and ordered lists are specified, add them both.
|
83
|
+
inject_block(1, -> { list(items, :ul) })
|
84
|
+
inject_block(1, -> { list(items, :ol) })
|
85
|
+
elsif @options[:ul]
|
86
|
+
# If only unordered list is specified, add it.
|
87
|
+
inject_block(2, -> { list(items, :ul) })
|
88
|
+
elsif @options[:ol]
|
89
|
+
# If only ordered list is specified, add it.
|
90
|
+
inject_block(2, -> { list(items, :ol) })
|
91
|
+
end
|
92
|
+
|
93
|
+
# Add definition list if specified.
|
94
|
+
inject_block(1, -> { list(items, :dl) }) if @options[:dl]
|
95
|
+
|
96
|
+
# Add blockquote if specified.
|
97
|
+
inject_block(1, -> { blockquote(items / 2) }) if @options[:bq]
|
98
|
+
|
99
|
+
# Add headers if specified.
|
100
|
+
inject_headers if @options[:headers]
|
101
|
+
|
102
|
+
# Add code block if specified.
|
103
|
+
inject_block(1, -> { code }) if @options[:code]
|
104
|
+
|
105
|
+
# Add table if specified.
|
106
|
+
inject_block(1, -> { table }) if @options[:table]
|
107
|
+
|
108
|
+
ensure_block_newlines
|
109
|
+
compress_newlines
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Rolls for zero with the specified odds.
|
115
|
+
def roll(odds)
|
116
|
+
Random.rand(0..odds).zero?
|
117
|
+
end
|
118
|
+
|
119
|
+
# Generates a list of items.
|
120
|
+
# @param [Integer] count The number of items to generate.
|
121
|
+
# @param [Symbol] type The type of list to generate (:ul, :ol, :dl).
|
122
|
+
# @return [String] The generated list.
|
123
|
+
def list(count, type)
|
124
|
+
ul = "\n\n<#{type}>\n"
|
125
|
+
|
126
|
+
count.times do
|
127
|
+
links = roll(4) && @options[:link]
|
128
|
+
em = roll(2) && @options[:decorate]
|
129
|
+
strong = roll(2) && @options[:decorate]
|
130
|
+
code = roll(4) && @options[:code]
|
131
|
+
mark = roll(6) && @options[:mark]
|
132
|
+
frag = fragment(1, 4).cap_first
|
133
|
+
long_frag = fragment(4, 8).cap_first
|
134
|
+
long_frag = inject_inline(long_frag, -> { link }) if links
|
135
|
+
long_frag = inject_inline(long_frag, -> { emphasis(:em) }) if em
|
136
|
+
long_frag = inject_inline(long_frag, -> { emphasis(:strong) }) if strong
|
137
|
+
long_frag = inject_inline(long_frag, -> { code_span }, 1) if code
|
138
|
+
long_frag = inject_inline(long_frag, -> { emphasis(:mark) }, 1) if mark
|
139
|
+
long_frag = long_frag.restore_spaces if links
|
140
|
+
if type == :dl
|
141
|
+
ul += "\t<dt>#{frag}</dt>\n"
|
142
|
+
ul += "\t<dd>#{long_frag}</dd>\n"
|
143
|
+
else
|
144
|
+
ul += "\t<li>#{long_frag}</li>\n"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
ul + "</#{type}>\n\n"
|
148
|
+
end
|
149
|
+
|
150
|
+
# Generates a blockquote.
|
151
|
+
# @param [Integer] count The number of items to generate.
|
152
|
+
# @param [Boolean] nested Whether the blockquote is nested.
|
153
|
+
# @return [String] The generated blockquote.
|
154
|
+
def blockquote(count, nested = false)
|
155
|
+
if count > 1 && !nested
|
156
|
+
level1 = Random.rand(1..count - 1).to_i
|
157
|
+
level2 = count - level1
|
158
|
+
else
|
159
|
+
level1 = 1
|
160
|
+
level2 = 0
|
161
|
+
end
|
162
|
+
cite = "\n<cite>— #{@generator.name}</cite>\n" unless nested
|
163
|
+
newline = nested ? '' : "\n\n"
|
164
|
+
quote = "#{newline}<blockquote>\n"
|
165
|
+
quote += paragraph(level1,
|
166
|
+
em: @options[:decorate],
|
167
|
+
strong: @options[:decorate],
|
168
|
+
links: @options[:link],
|
169
|
+
code: @options[:code],
|
170
|
+
mark: @options[:mark]).gsub(
|
171
|
+
/\n+/, "\n"
|
172
|
+
)
|
173
|
+
quote += blockquote(level2, true).strip if level2.positive?
|
174
|
+
"#{quote}#{cite}</blockquote>#{newline}"
|
175
|
+
end
|
176
|
+
|
177
|
+
# Generates a header.
|
178
|
+
# @param [Integer] level The level of the header (1-6).
|
179
|
+
# @return [String] The generated header.
|
180
|
+
def header(level)
|
181
|
+
level = 6 if level > 6
|
182
|
+
pre = level > 1 ? "\n\n" : ''
|
183
|
+
h = "#{pre}<h#{level}>"
|
184
|
+
h += fragment(2, 8).cap_first
|
185
|
+
h + "</h#{level}>\n\n"
|
186
|
+
end
|
187
|
+
|
188
|
+
# Injects headers in the output. Number injected depends on overall length
|
189
|
+
# of the input.
|
190
|
+
# @return [String] The output with injected headers.
|
191
|
+
def inject_headers
|
192
|
+
count = if @options[:grafs] == 1
|
193
|
+
1
|
194
|
+
elsif @options[:grafs] <= 3
|
195
|
+
2
|
196
|
+
elsif @options[:grafs] <= 5
|
197
|
+
4
|
198
|
+
elsif @options[:grafs] == 6
|
199
|
+
5
|
200
|
+
else
|
201
|
+
6
|
202
|
+
end
|
203
|
+
grafs = @output.split(/\n\n/).reverse
|
204
|
+
|
205
|
+
@output = header(1)
|
206
|
+
@output += "#{grafs.slice!(-1)}\n\n"
|
207
|
+
|
208
|
+
if count == 1
|
209
|
+
grafs = grafs.reverse
|
210
|
+
@output += grafs.join("\n\n")
|
211
|
+
return
|
212
|
+
end
|
213
|
+
|
214
|
+
level = 2
|
215
|
+
|
216
|
+
c = (grafs.length / count).to_i
|
217
|
+
|
218
|
+
while grafs.any? && level <= count
|
219
|
+
@output += header(level)
|
220
|
+
@output += grafs.slice!(grafs.length - c, c).join("\n\n")
|
221
|
+
level += 1
|
222
|
+
end
|
223
|
+
@output += grafs.join("\n\n")
|
224
|
+
compress_newlines
|
225
|
+
end
|
226
|
+
|
227
|
+
# Generates a random table. Length is determined by @options[:length]
|
228
|
+
# @return [String] The generated table.
|
229
|
+
def table
|
230
|
+
items = { short: 2, medium: 2, long: 4, very_long: 6 }[@options[:length]]
|
231
|
+
# Generates a random table.
|
232
|
+
table = "\n\n<table>\n"
|
233
|
+
table += "\t<tr>\n"
|
234
|
+
items.times do
|
235
|
+
table += "\t\t<th>#{fragment(1, 2).cap_first}</th>\n"
|
236
|
+
end
|
237
|
+
table += "\t</tr>\n"
|
238
|
+
items.times do
|
239
|
+
table += "\t<tr>\n"
|
240
|
+
items.times do
|
241
|
+
table += "\t\t<td>#{Random.rand(10_000)}</td>\n"
|
242
|
+
end
|
243
|
+
table += "\t</tr>\n"
|
244
|
+
end
|
245
|
+
table += "</table>\n\n"
|
246
|
+
table
|
247
|
+
end
|
248
|
+
|
249
|
+
# Generates a random code block
|
250
|
+
# @return [String] The generated code block.
|
251
|
+
def code
|
252
|
+
lang = @generator.code_lang
|
253
|
+
code = "\n\n<pre lang=\"#{lang}\"><code>\n"
|
254
|
+
code += "#{@generator.code_snippet(lang)}\n"
|
255
|
+
"#{code}</code></pre>\n\n"
|
256
|
+
end
|
257
|
+
|
258
|
+
# Generates a random code span
|
259
|
+
def code_span
|
260
|
+
@added[:code] = true
|
261
|
+
code = '<code>'
|
262
|
+
code += "#{@generator.words(Random.rand(1..5))} "
|
263
|
+
"#{code.strip}</code>"
|
264
|
+
end
|
265
|
+
|
266
|
+
# Generates a random emphasis tag
|
267
|
+
# @param [String] tag The tag to use for emphasis.
|
268
|
+
def emphasis(tag)
|
269
|
+
@added[tag] = true
|
270
|
+
"<#{tag}>#{fragment(1, 4)}</#{tag}>"
|
271
|
+
end
|
272
|
+
|
273
|
+
# Generates a random link
|
274
|
+
# @return [String] The generated link.
|
275
|
+
def link
|
276
|
+
@added[:link] = true
|
277
|
+
path = "/#{path_string(4, 8)}/#{path_string(4, 8)}"
|
278
|
+
title = fragment(4, 8).cap_first
|
279
|
+
"<a%%href=\"https://example.com#{path}\"%%title=\"#{title.preserve_spaces}\">#{fragment(1,
|
280
|
+
8).cap_first}</a>"
|
281
|
+
end
|
282
|
+
|
283
|
+
# Injects a block of text into the output.
|
284
|
+
# @param [Integer] count The number of blocks to inject.
|
285
|
+
# @param [Proc] block The block whose result to inject.
|
286
|
+
def inject_block(count, block)
|
287
|
+
grafs = @output.split(/\n\n/)
|
288
|
+
|
289
|
+
if grafs.length < 2
|
290
|
+
len = 1
|
291
|
+
else
|
292
|
+
len = Random.rand(1..grafs.length / 2).to_i
|
293
|
+
end
|
294
|
+
|
295
|
+
@output = "#{grafs.slice!(0, len).join("\n\n")}\n\n"
|
296
|
+
|
297
|
+
# count = { short: 4, medium: 8, long: 10, very_long: 12 }[@options[:length]]
|
298
|
+
@output += block.call
|
299
|
+
added = 1
|
300
|
+
while grafs.any?
|
301
|
+
len = Random.rand(1..grafs.length)
|
302
|
+
|
303
|
+
@output += "#{grafs.slice!(0, len).join("\n\n")}\n\n"
|
304
|
+
if added < count
|
305
|
+
@output += block.call
|
306
|
+
added += 1
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
compress_newlines
|
311
|
+
end
|
312
|
+
|
313
|
+
# Injects inline text into the output.
|
314
|
+
# @param [String] text The text to inject into.
|
315
|
+
# @param [Proc] block The block whose result to inject.
|
316
|
+
# @param [Integer] max The maximum number of times to inject the block.
|
317
|
+
def inject_inline(text, block, max = nil)
|
318
|
+
max ||= { short: 1, medium: 2, long: 3, very_long: 4 }[@options[:length]]
|
319
|
+
|
320
|
+
words = text.split(' ')
|
321
|
+
out = []
|
322
|
+
count = 0
|
323
|
+
while words.any?
|
324
|
+
if count >= max
|
325
|
+
out << words.slice!(0..-1)
|
326
|
+
break
|
327
|
+
else
|
328
|
+
el = block.call
|
329
|
+
out << words.slice!(0..Random.rand(1..words.length))
|
330
|
+
out << el if words.any?
|
331
|
+
count += 1
|
332
|
+
end
|
333
|
+
end
|
334
|
+
out.join(' ').term
|
335
|
+
end
|
336
|
+
|
337
|
+
# Generates a paragraph of Lorem Ipsum text.
|
338
|
+
# The `words` method generates a specified number of words.
|
339
|
+
# @param [Integer] count The number of paragraphs to generate.
|
340
|
+
# @param [Boolean] em Whether to include emphasis tags.
|
341
|
+
# @param [Boolean] strong Whether to include strong tags.
|
342
|
+
# @param [Boolean] links Whether to include links.
|
343
|
+
# @param [Boolean] code Whether to include code tags.
|
344
|
+
# @param [Boolean] mark Whether to include mark tags.
|
345
|
+
# @param [Array] force An array of tags to force.
|
346
|
+
# @return [String] The generated paragraph.
|
347
|
+
def paragraph(count, em: false, strong: false, links: false, code: false, mark: false, force: [])
|
348
|
+
|
349
|
+
output = ''
|
350
|
+
s = { short: 2, medium: 4, long: 6, very_long: 8 }[@options[:length]]
|
351
|
+
count.times do
|
352
|
+
p = @generator.sentences(s).join(' ')
|
353
|
+
|
354
|
+
should_em = force.include?(:em) || (em && roll(1))
|
355
|
+
should_strong = force.include?(:strong) || (strong && roll(1))
|
356
|
+
should_code = force.include?(:code) || (code && roll(6))
|
357
|
+
should_link = force.include?(:links) || (links && roll(4))
|
358
|
+
should_mark = force.include?(:mark) || (mark && roll(8))
|
359
|
+
p = inject_inline(p, -> { link }) if should_link
|
360
|
+
p = inject_inline(p, -> { emphasis('em') }) if should_em
|
361
|
+
p = inject_inline(p, -> { emphasis('strong') }) if should_strong
|
362
|
+
p = inject_inline(p, -> { emphasis('mark') }, 1) if should_mark
|
363
|
+
p = inject_inline(p, -> { code_span }, 1) if should_code
|
364
|
+
|
365
|
+
output += "<p>#{p.restore_spaces.cap_first.term('.')}</p>\n\n"
|
366
|
+
end
|
367
|
+
output
|
368
|
+
end
|
369
|
+
|
370
|
+
# Find block level tags and add newlines around them.
|
371
|
+
def ensure_block_newlines
|
372
|
+
# Adds newlines around block level tags.
|
373
|
+
@output.gsub!(/(<(h\d|div|blockquote|dl|ul|ol)>)/, "\n\n\\1")
|
374
|
+
@output.gsub!(%r{(</(h\d|div|blockquote|dl|ul|ol)>)\s*}, "\\1\n\n")
|
375
|
+
end
|
376
|
+
|
377
|
+
# Compresses newlines in the output.
|
378
|
+
# This method removes extra newlines from the output.
|
379
|
+
def compress_newlines
|
380
|
+
@output.compress_newlines!
|
381
|
+
end
|
382
|
+
|
383
|
+
# Generates a random fragment of text.
|
384
|
+
# The `words` method generates a specified number of words.
|
385
|
+
# @param [Integer] min The minimum number of words to generate.
|
386
|
+
# @param [Integer] max The maximum number of words to generate.
|
387
|
+
# @return [String] The generated fragment.
|
388
|
+
def fragment(min, max)
|
389
|
+
@generator.words(Random.rand(min..max)).no_term.downcase_first
|
390
|
+
end
|
391
|
+
|
392
|
+
# Generates a random string of characters.
|
393
|
+
# The `characters` method generates a specified number of characters.
|
394
|
+
def path_string(min, max)
|
395
|
+
@generator.characters(min, max, whole_words: false, whitespace: false).downcase
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|