hoe-manns 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.autotest +25 -0
  4. data/.gemnasium.yml +5 -0
  5. data/.idea/hoe-manns.iml +91 -0
  6. data/.idea/misc.xml +14 -0
  7. data/.idea/modules.xml +8 -0
  8. data/.idea/vcs.xml +6 -0
  9. data/.idea/workspace.xml +795 -0
  10. data/.index +173 -0
  11. data/.rspec +2 -0
  12. data/.rubocop.yml +39 -0
  13. data/.scrutinizer.yml +17 -0
  14. data/.travis.yml +28 -0
  15. data/CODE_OF_CONDUCT.md +17 -0
  16. data/CONTRIBUTING.md +33 -0
  17. data/Gemfile +37 -0
  18. data/Gemfile.lock +186 -0
  19. data/History.rdoc +7 -0
  20. data/LICENSE.rdoc +24 -0
  21. data/Manifest.txt +62 -0
  22. data/README.rdoc +114 -0
  23. data/Rakefile +104 -0
  24. data/VERSION +1 -0
  25. data/config.reek +111 -0
  26. data/etc/hoe-manns.cfg +1 -0
  27. data/lib/hoe/manns.rb +128 -0
  28. data/manual/layouts/default.erb +87 -0
  29. data/manual/lib/api-filter.rb +96 -0
  30. data/manual/lib/editorial-filter.rb +59 -0
  31. data/manual/lib/examples-filter.rb +230 -0
  32. data/manual/lib/links-filter.rb +111 -0
  33. data/manual/resources/css/manual.css +764 -0
  34. data/manual/resources/css/reset.css +112 -0
  35. data/manual/resources/fonts/GraublauWeb.otf +0 -0
  36. data/manual/resources/fonts/GraublauWebBold.otf +0 -0
  37. data/manual/resources/fonts/Inconsolata.otf +0 -0
  38. data/manual/resources/images/arrow_225_small.png +0 -0
  39. data/manual/resources/images/arrow_315_small.png +0 -0
  40. data/manual/resources/images/arrow_skip.png +0 -0
  41. data/manual/resources/images/cc-by.png +0 -0
  42. data/manual/resources/images/dialog-error.png +0 -0
  43. data/manual/resources/images/dialog-information.png +0 -0
  44. data/manual/resources/images/dialog-warning.png +0 -0
  45. data/manual/resources/images/emblem-important.png +0 -0
  46. data/manual/resources/images/help.png +0 -0
  47. data/manual/resources/images/information.png +0 -0
  48. data/manual/resources/images/magnifier.png +0 -0
  49. data/manual/resources/images/magnifier_left.png +0 -0
  50. data/manual/resources/images/page_white_code.png +0 -0
  51. data/manual/resources/images/page_white_copy.png +0 -0
  52. data/manual/resources/images/printer.png +0 -0
  53. data/manual/resources/images/question.png +0 -0
  54. data/manual/resources/images/scripts_code.png +0 -0
  55. data/manual/resources/images/wrap.png +0 -0
  56. data/manual/resources/images/wrapping.png +0 -0
  57. data/manual/resources/js/jquery-1.4.4.min.js +167 -0
  58. data/manual/resources/js/manual.js +30 -0
  59. data/manual/resources/js/sh.js +580 -0
  60. data/manual/resources/swf/clipboard.swf +0 -0
  61. data/manual/src/apidocs.page +17 -0
  62. data/manual/src/index.page +70 -0
  63. data/test/manns_spec.rb +54 -0
  64. data/test/spec_helper.rb +16 -0
  65. data.tar.gz.sig +0 -0
  66. metadata +542 -0
  67. metadata.gz.sig +0 -0
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # A manual filter to highlight content that needs editorial help.
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ #
8
+ #
9
+
10
+
11
+
12
+ ### A filter for making editorial marks in manual content.
13
+ ###
14
+ ### Editorial marks are XML processing instructions. There are several available types of
15
+ ### marks:
16
+ ###
17
+ ### <?ed "This is an editor's note." ?>
18
+ ### <?ed verify:"this content needs checking or verification" ?>
19
+ ###
20
+ class Hoe::ManualGen::EditorialFilter < Hoe::ManualGen::PageFilter
21
+
22
+ # PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
23
+ LinkPI = %r{
24
+ <\?
25
+ ed # Instruction Target
26
+ \s+
27
+ (\w+?) # type of editorial mark [$1]
28
+ :? # optional colon
29
+ "
30
+ (.*?) # content that should be edited [$2]
31
+ "
32
+ \s*
33
+ \?>
34
+ }x
35
+
36
+
37
+ ######
38
+ public
39
+ ######
40
+
41
+ ### Process the given +source+ for <?ed ... ?> processing-instructions
42
+ def process( source, page, metadata )
43
+ return source.gsub( LinkPI ) do |match|
44
+ # Grab the tag values
45
+ mark_type = $1
46
+ content = $2
47
+
48
+ self.generate_mark( page, mark_type, content )
49
+ end
50
+ end
51
+
52
+
53
+ ### Create an HTML fragment from the parsed LinkPI.
54
+ def generate_mark( current_page, mark_type, content )
55
+ return "%%(editorial %s-mark)%s%%" % [ mark_type, content ]
56
+ end
57
+
58
+
59
+ end
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/ruby
2
+ #encoding: utf-8
3
+ #
4
+ # A collection of standard filters for the manual generation tasklib.
5
+ #
6
+ # Authors:
7
+ # Michael Granger <ged@FaerieMUD.org>
8
+ #
9
+ #
10
+
11
+ # Dependencies deferred until #initialize
12
+
13
+
14
+
15
+ ### A filter for inline example code or command-line sessions -- does
16
+ ### syntax-checking for some languages and captioning.
17
+ ###
18
+ ### Examples are enclosed in XML processing instructions like so:
19
+ ###
20
+ ### <?example {language: ruby, testable: true, caption: "A fine example"} ?>
21
+ ### a = 1
22
+ ### puts a
23
+ ### <?end example ?>
24
+ ###
25
+ ### This will be pulled out into a preformatted section in the HTML,
26
+ ### highlighted as Ruby source, checked for valid syntax, and annotated with
27
+ ### the specified caption. Valid keys in the example PI are:
28
+ ###
29
+ ### language::
30
+ ### Specifies which (machine) language the example is in.
31
+ ### testable::
32
+ ### If set and there is a testing function for the given language, run it and append
33
+ ### any errors to the output.
34
+ ### caption::
35
+ ### A small blurb to put below the pulled-out example in the HTML.
36
+ class Hoe::ManualGen::ExamplesFilter < Hoe::ManualGen::PageFilter
37
+
38
+ DEFAULTS = {
39
+ :language => :ruby,
40
+ :line_numbers => :inline,
41
+ :tab_width => 4,
42
+ :hint => :debug,
43
+ :testable => false,
44
+ }
45
+
46
+ # PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
47
+ ExamplePI = %r{
48
+ <\?
49
+ example # Instruction Target
50
+ (?: # Optional instruction body
51
+ \s+
52
+ ((?: # [$1]
53
+ [^?]* # Run of anything but a question mark
54
+ | # -or-
55
+ \?(?!>) # question mark not followed by a closing angle bracket
56
+ )*)
57
+ )?
58
+ \?>
59
+ }x
60
+
61
+ EndPI = %r{ <\? end (?: \s+ example )? \s* \?> }x
62
+
63
+
64
+ ### Defer loading of dependenies until the filter is loaded
65
+ def initialize( *args )
66
+ require 'pathname'
67
+ require 'strscan'
68
+ require 'yaml'
69
+ require 'rcodetools/xmpfilter'
70
+ require 'digest/md5'
71
+ require 'tmpdir'
72
+ require 'erb'
73
+ end
74
+
75
+
76
+ ######
77
+ public
78
+ ######
79
+
80
+ ### Process the given +source+ for <?example ... ?> processing-instructions, calling out
81
+ def process( source, page, metadata )
82
+ scanner = StringScanner.new( source )
83
+
84
+ buffer = ''
85
+ until scanner.eos?
86
+ startpos = scanner.pos
87
+
88
+ # If we find an example
89
+ if scanner.skip_until( ExamplePI )
90
+ contents = ''
91
+
92
+ # Append the interstitial content to the buffer
93
+ if ( scanner.pos - startpos > scanner.matched.length )
94
+ offset = scanner.pos - scanner.matched.length - 1
95
+ buffer << scanner.string[ startpos..offset ]
96
+ end
97
+
98
+ # Append everything up to it to the buffer and save the contents of
99
+ # the tag
100
+ params = scanner[1]
101
+
102
+ # Now find the end of the example or complain
103
+ contentpos = scanner.pos
104
+ scanner.skip_until( EndPI ) or
105
+ raise "Unterminated example at line %d" %
106
+ [ scanner.string[0..scanner.pos].count("\n") ]
107
+
108
+ # Now build the example and append to the buffer
109
+ if ( scanner.pos - contentpos > scanner.matched.length )
110
+ offset = scanner.pos - scanner.matched.length - 1
111
+ contents = scanner.string[ contentpos..offset ]
112
+ end
113
+
114
+ trace "Processing with params: %p, contents: %p" % [ params, contents ]
115
+ buffer << self.process_example( params, contents, page )
116
+ else
117
+ break
118
+ end
119
+
120
+ end
121
+ buffer << scanner.rest
122
+ scanner.terminate
123
+
124
+ return buffer
125
+ end
126
+
127
+
128
+ ### Filter out 'example' macros, doing syntax highlighting, and running
129
+ ### 'testable' examples through a validation process appropriate to the
130
+ ### language the example is in.
131
+ def process_example( params, body, page )
132
+ options = self.parse_options( params )
133
+ caption = options.delete( :caption )
134
+ content = ''
135
+ lang = options.delete( :language ).to_s
136
+
137
+ # Test it if it's testable
138
+ if options[:testable]
139
+ content = test_content( body, lang, page )
140
+ else
141
+ content = body
142
+ end
143
+
144
+ # Strip trailing blank lines and syntax-highlight
145
+ content = highlight( content.strip, options, lang )
146
+ caption = %{<div class="caption">} + caption.to_s + %{</div>} if caption
147
+
148
+ return %{<notextile><div class="example #{lang}-example">%s%s</div></notextile>} %
149
+ [content, caption || '']
150
+ end
151
+
152
+
153
+ ### Parse an options hash for filtering from the given +args+, which can either
154
+ ### be a plain String, in which case it is assumed to be the name of the language the example
155
+ ### is in, or a Hash of configuration options.
156
+ def parse_options( args )
157
+ args = "{ #{args} }" unless args.strip[0] == ?{
158
+ args = YAML.load( args )
159
+
160
+ # Convert to Symbol keys and value
161
+ args.keys.each do |k|
162
+ newval = args.delete( k )
163
+ next if newval.nil? || (newval.respond_to?(:size) && newval.size == 0)
164
+ args[ k.to_sym ] = newval.respond_to?( :to_sym ) ? newval.to_sym : newval
165
+ end
166
+ return DEFAULTS.merge( args )
167
+ end
168
+
169
+
170
+ ### Test the given +content+ with a rule specific to the given +language+.
171
+ def test_content( body, language, page )
172
+ case language.to_sym
173
+ when :ruby
174
+ return self.test_ruby_content( body, page )
175
+
176
+ when :yaml
177
+ return self.test_yaml_content( body, page )
178
+
179
+ else
180
+ return body
181
+ end
182
+ end
183
+
184
+
185
+ ### Test the specified Ruby content for valid syntax
186
+ def test_ruby_content( source, page )
187
+ # $stderr.puts "Testing ruby content..."
188
+ libdir = Pathname.new( __FILE__ ).dirname.parent.parent.parent + 'lib'
189
+ extdir = Pathname.new( __FILE__ ).dirname.parent.parent.parent + 'ext'
190
+
191
+ options = Rcodetools::XMPFilter::INITIALIZE_OPTS.dup
192
+ options[:include_paths] |= [ libdir.to_s, extdir.to_s ]
193
+ options[:width] = 60
194
+
195
+ if page.config['example_prelude']
196
+ prelude = page.config['example_prelude']
197
+ trace " prepending prelude:\n#{prelude}"
198
+ source = prelude.strip + "\n" + source.strip
199
+ else
200
+ trace " no prelude; page config is: %p" % [ page.config ]
201
+ end
202
+
203
+ rval = Rcodetools::XMPFilter.run( source, options )
204
+
205
+ trace "test output: ", rval
206
+ return rval.join
207
+ rescue Exception => err
208
+ return "%s while testing: %s\n %s" %
209
+ [ err.class.name, err.message, err.backtrace.join("\n ") ]
210
+ end
211
+
212
+
213
+ ### Test the specified YAML content for valid syntax
214
+ def test_yaml_content( source, metadata )
215
+ YAML.load( source )
216
+ rescue YAML::Error => err
217
+ return "# Invalid YAML: " + err.message + "\n" + source
218
+ else
219
+ return source
220
+ end
221
+
222
+
223
+ ### Highlights the given +content+ in language +lang+.
224
+ def highlight( content, options, lang )
225
+ source = ERB::Util.html_escape( content )
226
+ return %Q{\n\n<pre class="brush:#{lang}">#{source}</pre>\n\n}
227
+ end
228
+
229
+ end
230
+
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # A manual filter to generate links from the page catalog.
4
+ #
5
+ # Authors:
6
+ # * Michael Granger <ged@FaerieMUD.org>
7
+ # * Mahlon E. Smith <mahlon@martini.nu>
8
+ #
9
+ #
10
+
11
+
12
+ ### A filter for generating links from the page catalog. This allows you to refer to other pages
13
+ ### in the source and have them automatically updated as the structure of the manual changes.
14
+ ###
15
+ ### Links are XML processing instructions. Pages can be referenced in one of several ways:
16
+ ###
17
+ ### <?link Page Title ?>
18
+ ### <?link "click here":Page Title ?>
19
+ ### <?link Page Title #section_id ?>
20
+ ### <?link "click here":Page Title#section_id ?>
21
+ ###
22
+ ### This first form links to a page by title. Link text defaults to the page title unless an
23
+ ### optional quoted string is prepended. If you want to link to an anchor inside the page, include
24
+ ### its ID with a hash mark after the title.
25
+ ###
26
+ ### <?link path/to/Catalog.page ?>
27
+ ### <?link "click here":path/to/Catalog.page ?>
28
+ ### <?link path/to/Catalog.page#section_id ?>
29
+ ### <?link "click here":path/to/Catalog.page#section_id ?>
30
+ ###
31
+ ### The second form links to a page by its path relative to the base manual source directory.
32
+ ### Again, the link text defaults to the page title, or can be overriden via a prepended string,
33
+ ### and you can link into a page with an appended ID.
34
+ class Hoe::ManualGen::LinksFilter < Hoe::ManualGen::PageFilter
35
+
36
+ # PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
37
+ LinkPI = %r{
38
+ <\?
39
+ link # Instruction Target
40
+ \s+
41
+ (?:"
42
+ (.*?) # Optional link text [$1]
43
+ ":)?
44
+ (.*?) # Title or path [$2]
45
+ \s*
46
+ (\#\w+)? # Fragment [$3]
47
+ \s+
48
+ \?>
49
+ }x
50
+
51
+
52
+ ######
53
+ public
54
+ ######
55
+
56
+ ### Process the given +source+ for <?link ... ?> processing-instructions, calling out
57
+ def process( source, page, metadata )
58
+ return source.gsub( LinkPI ) do |match|
59
+ # Grab the tag values
60
+ link_text = $1
61
+ reference = $2
62
+ fragment = $3
63
+
64
+ self.generate_link( page, reference, link_text, fragment )
65
+ end
66
+ end
67
+
68
+
69
+ ### Create an HTML link fragment from the parsed LinkPI.
70
+ def generate_link( current_page, reference, link_text=nil, fragment=nil )
71
+
72
+ if other_page = self.find_linked_page( current_page, reference )
73
+ href_path = other_page.sourcefile.relative_path_from( current_page.sourcefile.dirname )
74
+ href = href_path.to_s.gsub( '.page', '.html' )
75
+
76
+ if link_text
77
+ return %{<a href="#{href}#{fragment}">#{link_text}</a>}
78
+ else
79
+ return %{<a href="#{href}#{fragment}">#{other_page.title}</a>}
80
+ end
81
+ else
82
+ link_text ||= reference
83
+ error_message = "Could not find a link for reference '%s'" % [ reference ]
84
+ $stderr.puts( error_message )
85
+ return %{<a href="#" title="#{error_message}" class="broken-link">#{link_text}</a>}
86
+ end
87
+ end
88
+
89
+
90
+ ### Lookup a page +reference+ in the catalog. +reference+ can be either a
91
+ ### path to the .page file, relative to the manual root path, or a page title.
92
+ ### Returns a matching Page object, or nil if no match is found.
93
+ def find_linked_page( current_page, reference )
94
+
95
+ catalog = current_page.catalog
96
+
97
+ # Lookup by page path
98
+ if reference =~ /\.page$/
99
+ return catalog.uri_index[ reference ]
100
+
101
+ # Lookup by page title
102
+ else
103
+ return catalog.title_index[ reference ]
104
+ end
105
+ end
106
+ end
107
+
108
+
109
+
110
+
111
+