syntaxi 0.5.0

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.
Files changed (2) hide show
  1. data/lib/syntaxi.rb +274 -0
  2. metadata +49 -0
@@ -0,0 +1,274 @@
1
+ require 'syntax/convertors/html'
2
+
3
+ # Syntaxi is a class for formatting code blocks in your HTML. It can:
4
+ # * Add line numbers
5
+ # * Wrap long lines automatically
6
+ # * Perform syntax coloring using Jamis Buck's Syntax gem
7
+ #
8
+ # == How to Write your Code Block
9
+ #
10
+ # In order for Syntaxi to do its magic, you'll need to write your code blocks
11
+ # like this:
12
+ #
13
+ # [code lang="ruby"]
14
+ # def foo
15
+ # puts 'bar'
16
+ # end
17
+ # [/code]
18
+ #
19
+ # The square bracket syntax allows Syntaxi to work seamlessly in HTML,
20
+ # Markdown, and Textile alike. The +lang+ attribute specifies the language
21
+ # of the code block.
22
+ #
23
+ # == How to Process the Text
24
+ #
25
+ # Having Syntaxi format your code containing the special code blocks is easy.
26
+ # Lets say your text is stored in +text+. To format this text simply do the
27
+ # following:
28
+ #
29
+ # text = Syntaxi.new(text).process
30
+ #
31
+ # == Syntax coloring
32
+ #
33
+ # If the +lang+ attribute you specified in your opening code block tag
34
+ # is recognized by Jamis Buck's Syntax gem, the block will have syntax coloring
35
+ # applied to it automatically. See the documentation for Syntax to learn
36
+ # more about how to style the different spans it produces.
37
+ #
38
+ # == Line Numbers
39
+ #
40
+ # Syntaxi can also add line numbers to your code blocks. It can do this in two
41
+ # different ways:
42
+ # * Inline line numbering will add line numbers at the beginning of each line.
43
+ # * Floating line numbering will create a <div> to contain the line numbers and
44
+ # float that <div> left, so that selecting text from the code block will
45
+ # select only the code, and not the line numbers.
46
+ #
47
+ # By default, line numbering is set to +inline+. To change the line number
48
+ # method, simply call line_number_method= like so:
49
+ #
50
+ # Syntaxi.line_number_method = 'floating'
51
+ #
52
+ # Valid values are 'none', 'inline', and 'floating'
53
+ #
54
+ # == Line Wrap
55
+ #
56
+ # Because your code blocks will often have lines that are longer than the
57
+ # available width, Syntaxi can wrap long lines for you. If possible the line
58
+ # break will done on a space. No line numbers will appear on the wrapped
59
+ # portions of long lines (but subsequent lines will still have the right
60
+ # line numbers).
61
+ #
62
+ # By default, line wrap is enabled and wraps on column 60. To disable line
63
+ # wrap, simply call wrap_enabled= with +false+:
64
+ #
65
+ # Syntaxi.wrap_enabled = false
66
+ #
67
+ # To change the column on which to wrap, call wrap_at_column= like this:
68
+ #
69
+ # Syntaxi.wrap_at_column = 70
70
+ #
71
+ # == Where to set the Options
72
+ #
73
+ # Since the configuration options are stored as class variables, you need only change
74
+ # them once, and all future instances of Syntaxi will use the new values.
75
+ # If your entire application will use the same values, simply set the values
76
+ # to your liking at the beginning of execution. In Ruby on Rails, an ideal
77
+ # place to do this is in [RAILS_ROOT]/config/environment.rb.
78
+ class Syntaxi
79
+
80
+ # Specifies the line numbering method
81
+ # one of [none|floating|inline]
82
+ @@line_number_method = 'inline'
83
+
84
+ # Sets the line number method. Valid values are 'none', 'floating', or
85
+ # 'inline'. Default is +'inline'+
86
+ #
87
+ # See Syntaxi class documentation for more information.
88
+ def self.line_number_method=(meth)
89
+ %w{none floating inline}.include?(meth) || raise("Invalid Line Number Method. Must be one of [none|floating|inline].")
90
+ @@line_number_method = meth
91
+ end
92
+
93
+ # specifies whether or not to wrap long lines
94
+ @@wrap_enabled = true
95
+
96
+ # Sets whether or not to wrap long lines. Defaults is +true+
97
+ #
98
+ # See Syntaxi class documentation for more information.
99
+ def self.wrap_enabled=(enabled)
100
+ @@wrap_enabled = enabled
101
+ end
102
+
103
+ # Specifies the column on which to wrap if line wrap is enabled
104
+ @@wrap_at_column = 60
105
+
106
+ # Sets the column on which to wrap if line wrap is enabled. Defaults to
107
+ # +65+
108
+ #
109
+ # See Syntaxi class documentation for more information.
110
+ def self.wrap_at_column=(col)
111
+ @@wrap_at_column = col
112
+ end
113
+
114
+ # Instance variable to hold the code
115
+ @text
116
+
117
+ def initialize(text) #:nodoc:
118
+ @text = text
119
+ end
120
+
121
+ # Processes the text that this object was initialized with according to the
122
+ # configuration parameters.
123
+ def process
124
+ # pick out any existing <code> blocks and replace with a placeholder
125
+ ignores = {}
126
+ ignore_index = 0
127
+ @text.gsub!(/<code.*?code>/m){
128
+ ignore_index += 1
129
+ ignores[ignore_index] = $&
130
+ "<!--syntaxi-code-ignore-block-" + ignore_index.to_s + "-->"
131
+ }
132
+
133
+ # format the specified sections
134
+ @text.gsub!(/\[code.+?lang\s?=\s?['"](.*?)['"].*?\](.*?)\[\/code\]/m){
135
+ language = $1
136
+ code = $2
137
+
138
+ # fix any spacy weirdness
139
+ code = code.sub(/^\s*\n*/, '')
140
+ code = code.gsub(/\t/, ' ')
141
+ code = code.gsub(/\r\n/, "\n")
142
+
143
+ # count the number of lines in this code block for later
144
+ line_count = code.split("\n").length
145
+
146
+ # do line wrapping if required
147
+ code = wrap_long_lines(code, line_count) if @@wrap_enabled
148
+
149
+ # do the syntax coloring
150
+ code = Syntax::Convertors::HTML.for_syntax(language).convert(code, false)
151
+
152
+ # do the line numbering
153
+ code =
154
+ case @@line_number_method
155
+ when 'none'
156
+ add_no_line_numbers(code)
157
+ when 'floating'
158
+ add_floating_line_numbers(code, line_count)
159
+ when 'inline'
160
+ add_inline_line_numbers(code, line_count)
161
+ end
162
+
163
+ # return the code to the gsub
164
+ code
165
+ }
166
+
167
+ # put the existing <code> blocks back in
168
+ @text.gsub!(/<!--syntaxi-code-ignore-block-(\d+?)-->/) {
169
+ ignores[$1.to_i]
170
+ }
171
+
172
+ # return all the processed text
173
+ @text
174
+ end
175
+
176
+ private
177
+
178
+ # No line numbering required, so just wrap the code block
179
+ def add_no_line_numbers(code) #:nodoc:
180
+ code.gsub!(/\a/, '')
181
+ "<pre><code>" + code + "</code></pre>"
182
+ end
183
+
184
+ # Inline line numbers are just numbers at the beginning of the actual line
185
+ # followed by some spaces.
186
+ def add_inline_line_numbers(code, lines) #:nodoc:
187
+ i = 0
188
+ out = ''
189
+ width = lines.to_s.length
190
+ code.each_line do |line|
191
+ if line =~ /\a/
192
+ out += line.sub(/\a/, '')
193
+ else
194
+ i += 1
195
+ out += "<span class=\"line_number\">" + i.to_s.rjust(width) + "</span>" + " " + line
196
+ end
197
+ end
198
+ "<pre><code>" + out + "</code></pre>"
199
+ end
200
+
201
+ # Floating line numbers are created by floating the line numbers left. This
202
+ # makes is possible to select the code in the web browser without also
203
+ # selecting the line numbers. Very useful, but can act strangely in some
204
+ # browsers, so use with caution
205
+ def add_floating_line_numbers(code, lines) #:nodoc:
206
+ i = 0
207
+ out_numbers = '<pre style="overflow: hidden;"><code class="line_number" style="float: left; margin-right: 1em">'
208
+ out_code = '<code>'
209
+ width = lines.to_s.length
210
+ code.each_line do |line|
211
+ if line =~ /\a/
212
+ out_numbers += "&nbsp;\n"
213
+ out_code += line.sub(/\a/, '')
214
+ else
215
+ i += 1
216
+ out_numbers += i.to_s.rjust(width).gsub(/ /, '&nbsp;') + "\n"
217
+ out_code += line.sub(/^ */) {
218
+ $& ? $&.gsub(/ /, '&nbsp;') : ''
219
+ }
220
+ end
221
+ end
222
+ out_numbers.chomp + '</code>' + out_code + '</code></pre>'
223
+ end
224
+
225
+ # Wrap long lines using intelligent line wrap (indent wrapped lines to match
226
+ # the indent of the line being wrapped)
227
+ def wrap_long_lines(code, lines) #:nodoc:
228
+ out = ''
229
+ line_wrap_indicator = "\a" # bell character is not modified by Syntax
230
+ line_num_width = lines.to_s.length # for inline line numbering
231
+
232
+ code.each_line do |line|
233
+ if line.length > @@wrap_at_column
234
+
235
+ # determine proper indent
236
+ line =~ /^\s*/
237
+ if @@line_number_method == 'inline'
238
+ indent = ' ' + (' ' * ($&.length + line_num_width))
239
+ else
240
+ indent = ' ' * $&.length
241
+ end
242
+
243
+ # split this line up into mutliple lines. break on spaces if possible
244
+ first_line = true
245
+ max_line_length = @@wrap_at_column
246
+ while line
247
+ if line.length < max_line_length
248
+ # last part
249
+ out += line_wrap_indicator + indent + line
250
+ line = nil
251
+ elsif i = line.rindex(/\s/, max_line_length)
252
+ # long part with a space in it
253
+ out += line_wrap_indicator + indent unless first_line
254
+ out += line[0, i + 1] + "\n"
255
+ line = line[i + 1, line.length]
256
+ else
257
+ # long part with no space in it
258
+ out += line_wrap_indicator + indent unless first_line
259
+ out += line[0, max_line_length] + "\n"
260
+ line = line[max_line_length, line.length]
261
+ end
262
+ # not the first line anymore
263
+ first_line = false
264
+ max_line_length = @@wrap_at_column - indent.length
265
+ end
266
+
267
+ else
268
+ out += line
269
+ end
270
+ end
271
+ out
272
+ end
273
+
274
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: syntaxi
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.5.0
7
+ date: 2005-12-12 00:00:00 -08:00
8
+ summary: "Syntaxi formats code blocks in text (line number, line wrap, syntax color)"
9
+ require_paths:
10
+ - lib
11
+ email: tom@cube6media.com
12
+ homepage: http://syntaxi.rubyforge.org
13
+ rubyforge_project: syntaxi
14
+ description:
15
+ autorequire: syntaxi
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Tom Werner
31
+ files:
32
+ - lib/syntaxi.rb
33
+ test_files: []
34
+ rdoc_options: []
35
+ extra_rdoc_files: []
36
+ executables: []
37
+ extensions: []
38
+ requirements: []
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: syntax
42
+ version_requirement:
43
+ version_requirements: !ruby/object:Gem::Version::Requirement
44
+ requirements:
45
+ -
46
+ - "="
47
+ - !ruby/object:Gem::Version
48
+ version: 1.0.0
49
+ version: