wallyqs-org-ruby 0.6.1 → 0.8.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 (122) hide show
  1. data/History.txt +41 -11
  2. data/README.rdoc +55 -50
  3. data/bin/org-ruby +11 -5
  4. data/lib/org-ruby.rb +20 -27
  5. data/lib/org-ruby/headline.rb +0 -10
  6. data/lib/org-ruby/html_output_buffer.rb +224 -143
  7. data/lib/org-ruby/html_symbol_replace.rb +359 -340
  8. data/lib/org-ruby/line.rb +91 -30
  9. data/lib/org-ruby/output_buffer.rb +147 -139
  10. data/lib/org-ruby/parser.rb +45 -111
  11. data/lib/org-ruby/regexp_helper.rb +52 -57
  12. data/lib/org-ruby/textile_output_buffer.rb +90 -37
  13. data/lib/org-ruby/textile_symbol_replace.rb +360 -341
  14. metadata +39 -200
  15. data/.bnsignore +0 -18
  16. data/.gitignore +0 -2
  17. data/Gemfile +0 -7
  18. data/Gemfile.lock +0 -36
  19. data/Rakefile +0 -33
  20. data/TAGS +0 -167
  21. data/announcement.txt +0 -24
  22. data/org-ruby.gemspec +0 -40
  23. data/spec/data/freeform-example.org +0 -113
  24. data/spec/data/freeform.org +0 -111
  25. data/spec/data/hyp-planning.org +0 -335
  26. data/spec/data/remember.org +0 -53
  27. data/spec/headline_spec.rb +0 -65
  28. data/spec/html_examples/advanced-code.html +0 -81
  29. data/spec/html_examples/advanced-code.org +0 -106
  30. data/spec/html_examples/advanced-lists.html +0 -31
  31. data/spec/html_examples/advanced-lists.org +0 -31
  32. data/spec/html_examples/block_code.html +0 -28
  33. data/spec/html_examples/block_code.org +0 -35
  34. data/spec/html_examples/blockcomment.html +0 -3
  35. data/spec/html_examples/blockcomment.org +0 -15
  36. data/spec/html_examples/blockquote.html +0 -7
  37. data/spec/html_examples/blockquote.org +0 -13
  38. data/spec/html_examples/center.html +0 -6
  39. data/spec/html_examples/center.org +0 -7
  40. data/spec/html_examples/code-comment.html +0 -18
  41. data/spec/html_examples/code-comment.org +0 -22
  42. data/spec/html_examples/code-syntax.html +0 -98
  43. data/spec/html_examples/code-syntax.org +0 -99
  44. data/spec/html_examples/comment-trees.html +0 -4
  45. data/spec/html_examples/comment-trees.org +0 -13
  46. data/spec/html_examples/custom-seq-todo.html +0 -15
  47. data/spec/html_examples/custom-seq-todo.org +0 -24
  48. data/spec/html_examples/custom-todo.html +0 -15
  49. data/spec/html_examples/custom-todo.org +0 -24
  50. data/spec/html_examples/custom-typ-todo.html +0 -15
  51. data/spec/html_examples/custom-typ-todo.org +0 -24
  52. data/spec/html_examples/deflist.html +0 -6
  53. data/spec/html_examples/deflist.org +0 -6
  54. data/spec/html_examples/entities.html +0 -4
  55. data/spec/html_examples/entities.org +0 -11
  56. data/spec/html_examples/escape-pre.html +0 -6
  57. data/spec/html_examples/escape-pre.org +0 -6
  58. data/spec/html_examples/export-exclude-only.html +0 -13
  59. data/spec/html_examples/export-exclude-only.org +0 -81
  60. data/spec/html_examples/export-keywords.html +0 -4
  61. data/spec/html_examples/export-keywords.org +0 -18
  62. data/spec/html_examples/export-tags.html +0 -8
  63. data/spec/html_examples/export-tags.org +0 -82
  64. data/spec/html_examples/export-title.html +0 -2
  65. data/spec/html_examples/export-title.org +0 -4
  66. data/spec/html_examples/footnotes.html +0 -10
  67. data/spec/html_examples/footnotes.org +0 -7
  68. data/spec/html_examples/html-literal.html +0 -2
  69. data/spec/html_examples/html-literal.org +0 -6
  70. data/spec/html_examples/inline-formatting.html +0 -20
  71. data/spec/html_examples/inline-formatting.org +0 -33
  72. data/spec/html_examples/inline-images.html +0 -10
  73. data/spec/html_examples/inline-images.org +0 -15
  74. data/spec/html_examples/link-features.html +0 -8
  75. data/spec/html_examples/link-features.org +0 -19
  76. data/spec/html_examples/lists.html +0 -23
  77. data/spec/html_examples/lists.org +0 -47
  78. data/spec/html_examples/metadata-comment.html +0 -27
  79. data/spec/html_examples/metadata-comment.org +0 -30
  80. data/spec/html_examples/only-list.html +0 -5
  81. data/spec/html_examples/only-list.org +0 -3
  82. data/spec/html_examples/only-table.html +0 -6
  83. data/spec/html_examples/only-table.org +0 -5
  84. data/spec/html_examples/skip-header.html +0 -3
  85. data/spec/html_examples/skip-header.org +0 -28
  86. data/spec/html_examples/skip-table.html +0 -4
  87. data/spec/html_examples/skip-table.org +0 -19
  88. data/spec/html_examples/subsupscript-nil.html +0 -3
  89. data/spec/html_examples/subsupscript-nil.org +0 -6
  90. data/spec/html_examples/subsupscript.html +0 -3
  91. data/spec/html_examples/subsupscript.org +0 -5
  92. data/spec/html_examples/tables.html +0 -35
  93. data/spec/html_examples/tables.org +0 -50
  94. data/spec/html_examples/text.html +0 -2
  95. data/spec/html_examples/text.org +0 -16
  96. data/spec/line_spec.rb +0 -155
  97. data/spec/output_buffer_spec.rb +0 -19
  98. data/spec/parser_spec.rb +0 -152
  99. data/spec/regexp_helper_spec.rb +0 -57
  100. data/spec/spec_helper.rb +0 -20
  101. data/spec/textile_examples/block_code.org +0 -35
  102. data/spec/textile_examples/block_code.textile +0 -29
  103. data/spec/textile_examples/blockquote.org +0 -13
  104. data/spec/textile_examples/blockquote.textile +0 -11
  105. data/spec/textile_examples/center.org +0 -7
  106. data/spec/textile_examples/center.textile +0 -6
  107. data/spec/textile_examples/footnotes.org +0 -7
  108. data/spec/textile_examples/footnotes.textile +0 -8
  109. data/spec/textile_examples/keywords.org +0 -13
  110. data/spec/textile_examples/keywords.textile +0 -11
  111. data/spec/textile_examples/links.org +0 -11
  112. data/spec/textile_examples/links.textile +0 -10
  113. data/spec/textile_examples/lists.org +0 -36
  114. data/spec/textile_examples/lists.textile +0 -20
  115. data/spec/textile_examples/single-space-plain-list.org +0 -13
  116. data/spec/textile_examples/single-space-plain-list.textile +0 -10
  117. data/spec/textile_examples/tables.org +0 -50
  118. data/spec/textile_examples/tables.textile +0 -40
  119. data/spec/textile_output_buffer_spec.rb +0 -21
  120. data/tasks/test_case.rake +0 -49
  121. data/test/test_orgmode_parser.rb +0 -0
  122. data/util/gen-special-replace.el +0 -37
@@ -1,17 +1,47 @@
1
- == 0.6.1 / 2012-02-25
1
+ == 0.8.0 / 2013-02-10
2
2
 
3
- * Major Enhancements
4
- * Added encoding directive to support Ruby 1.9.2
5
- * Included .org support for Tilt templates (thanks to crnixon)
6
- * #+BEGIN/END_SRC lang code blocks are embedded in code tags with class that specifies the coding language
7
- * CodeRay is used to give code syntax highlight support to #+BEGIN/END_SRC blocks
3
+ * A lot of refactoring work and bugfixes contributed by vonavi (many thanks!)
4
+ * Raw HTML is supported with #+html
5
+ * Code indentation for code blocks is fixed now
6
+ * Support for definition lists is improved
7
+ * Bugfix for when including headlines in center and quote blocks.
8
+ * Indentation of HTML output improved
9
+ * Improvements to entities support for Textile and HTML outputs
8
10
 
9
- * Minor Enhancements
10
- * Angle links in org-mode are embedded in anchor tags on html output
11
- * Headlines with the COMMENT keyword, and the PROPERTIES drawer are not exported
11
+ == 0.7.2 / 2012-10-07
12
12
 
13
- * Bug fixes
14
- * Fixed bug with InlineExampleRegexp when a colon is at the beginning of a block
13
+ * Many fixes to the regular expressions used for emphasis, contributed by [[http://github.com/vonavi][vonavi]]
14
+ * Bug fix for when a table starts with a headline, thanks to [[http://github/til][til]]
15
+ * Asterisk can be used for definition lists too
16
+ * Use text lexer as default option for Pygments and Coderay when no language is specified
17
+
18
+ == 0.7.1 / 2012-08-04
19
+
20
+ * Make source code blocks from lisp dialects use Pygments scheme lexer
21
+ * Bugfix: Make Coderay fallback to text lexer when unsupported lang is set
22
+
23
+ == 0.7.0 / 2012-07-08
24
+
25
+ * Highlight source code blocks using Pygments or CodeRay when available
26
+
27
+ == 0.6.4 / 2012-07-08
28
+
29
+ * Fixed lists behavior when code fragments, tables and examples were present
30
+ * Remove code tags with lang class and use instead src-:lang like org-exporter
31
+ * Fixed property drawers to consider properties with hyphens like :noweb-ref:
32
+
33
+ == 0.6.3 / 2012-05-22
34
+
35
+ * Minor enhancement: Correct handling of .org URIs in HTML markup routine (thanks, rayl)
36
+
37
+ == 0.6.1 / 2012-04-14
38
+
39
+ * Added encoding directive to support Ruby 1.9.2
40
+ * Headlines with the COMMENT keyword, and the PROPERTIES drawer are not exported
41
+ * Angle links in org-mode are embedded in anchor tags on html output
42
+ * #+BEGIN/END_SRC lang code blocks are embedded in code tags with class that specifies the coding language
43
+ * Fixed bug in code blocks when a colon was at the beginning
44
+ * More than five dashes create an horizontal rule in html output
15
45
 
16
46
  == 0.6.0 / 2011-09-03
17
47
 
@@ -1,67 +1,72 @@
1
- org-ruby
2
- by Brian Dewey
3
- http://github.com/bdewey/org-ruby
1
+ = org-ruby
2
+ <em>Originally by Brian Dewey</em> (http://github.com/bdewey/org-ruby)
4
3
 
5
- == DESCRIPTION:
4
+ {<img src="https://secure.travis-ci.org/wallyqs/org-ruby.png?branch=master" alt="Build Status" />}[http://travis-ci.org/wallyqs/org-ruby]
6
5
 
7
- This gem contains Ruby routines for parsing org-mode files.The most
8
- significant thing this library does today is convert org-mode files to
9
- HTML or textile. Currently, you cannot do much to customize the
10
- conversion. The supplied textile conversion is optimized for
11
- extracting "content" from the orgfile as opposed to "metadata."
6
+ An {org-mode}[http://orgmode.org] parser written in Ruby. The most significant thing this library does today is convert org-mode files to HTML or Textile.
7
+ Currently, you cannot do much to customize the conversion. The supplied textile conversion is optimized for extracting
8
+ “content” from the orgfile as opposed to “metadata.”
12
9
 
13
- == FEATURES/PROBLEMS:
10
+ == Installation
14
11
 
15
- * Converts org-mode files to HTML or Textile
16
- * Supports tables, block quotes, and block code
17
- * Supports bold, italic, underline, strikethrough, and code inline formatting.
18
- * Supports hyperlinks that are in double-brackets
19
- * Supports +.org+ views in Rails through Tilt.
20
- * Upcoming: Handle export options specified in the org buffer.
21
-
22
- == SYNOPSIS:
12
+ gem install org-ruby
23
13
 
24
- From the command line:
25
-
26
- org-ruby sample.org
27
-
28
- ...will output a HTML version of sample.org.
29
-
30
- org-ruby --translate textile sample.org
31
-
32
- ...will output a textile version of sample.org.
14
+ == Usage
33
15
 
34
16
  From Ruby code:
35
17
 
36
- Orgmode::Parser.new(data)
18
+ require 'org-ruby'
37
19
 
38
- ...will construct a new +Parser+ object.
20
+ # Renders HTML
21
+ Orgmode::Parser.new("* Hello world!).to_html
22
+ # => "<h1>Hello world!</h1>\n"
39
23
 
40
- == INSTALL:
24
+ # Renders Textile
25
+ Orgmode::Parser.new("* Hello world!).to_textile
26
+ # => "h1. Hello world!\n"
41
27
 
42
- sudo gem install org-ruby
28
+ It can also be used from the command line:
43
29
 
44
- == LICENSE:
30
+ org-ruby sample.org --translate html
45
31
 
46
- (The MIT License)
32
+ ...will output a HTML version of sample.org.
47
33
 
48
- Copyright (c) 2009 Brian Dewey
34
+ org-ruby --translate textile sample.org
49
35
 
50
- Permission is hereby granted, free of charge, to any person obtaining
51
- a copy of this software and associated documentation files (the
52
- 'Software'), to deal in the Software without restriction, including
53
- without limitation the rights to use, copy, modify, merge, publish,
54
- distribute, sublicense, and/or sell copies of the Software, and to
55
- permit persons to whom the Software is furnished to do so, subject to
56
- the following conditions:
36
+ ...will output a textile version of sample.org.
57
37
 
58
- The above copyright notice and this permission notice shall be
59
- included in all copies or substantial portions of the Software.
38
+ == Features
60
39
 
61
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
62
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
64
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
65
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
66
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
67
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40
+ * Converts org-mode files to HTML or Textile
41
+ * Supports tables, block quotes, code blocks, and html blocks
42
+ * Supports bold, italic, underline, strikethrough, and code inline formatting.
43
+ * Supports hyperlinks that are in double-brackets
44
+ * Supports definition lists
45
+ * Supports footnotes
46
+ * Supports +.org+ views in Rails through Tilt.
47
+ * Code syntax highlight of code blocks using Pygments.rb or Coderay when available
48
+
49
+ == License
50
+
51
+ (The MIT License)
52
+
53
+ Copyright (c) 2009 Brian Dewey
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining
56
+ a copy of this software and associated documentation files (the
57
+ 'Software'), to deal in the Software without restriction, including
58
+ without limitation the rights to use, copy, modify, merge, publish,
59
+ distribute, sublicense, and/or sell copies of the Software, and to
60
+ permit persons to whom the Software is furnished to do so, subject to
61
+ the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be
64
+ included in all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
67
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
69
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
71
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
72
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,11 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
-
3
- require File.expand_path(
4
- File.join(File.dirname(__FILE__), %w[.. lib org-ruby]))
2
+ require 'org-ruby'
5
3
  require 'optparse'
6
4
 
7
- # Put your code here
8
-
9
5
  options = {}
10
6
  options_parser = OptionParser.new do |opts|
11
7
  options[:help] = false
@@ -25,10 +21,20 @@ options_parser = OptionParser.new do |opts|
25
21
  "Translate the ORG file to the specified format.") do |v|
26
22
  options[:format] = v
27
23
  end
24
+
25
+ opts.on("-v", "--version", "Print version") do |v|
26
+ options[:version] = true
27
+ end
28
28
  end
29
29
 
30
30
  begin
31
31
  options_parser.parse!
32
+
33
+ if options[:version]
34
+ puts OrgRuby::VERSION
35
+ exit
36
+ end
37
+
32
38
  if (ARGV.length == 0) then
33
39
  puts options_parser
34
40
  else
@@ -1,14 +1,27 @@
1
- unless defined? ::OrgRuby
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
2
 
3
- # Default to UTF-8 in Ruby 1.9 rather than ASCII
4
- if defined? Encoding and Encoding.respond_to? 'default_external='
5
- Encoding.default_external = Encoding.default_internal = Encoding::UTF_8
6
- end
3
+ # internal requires
4
+ require 'org-ruby/parser'
5
+ require 'org-ruby/regexp_helper'
6
+ require 'org-ruby/line'
7
+ require 'org-ruby/headline'
8
+ require 'org-ruby/output_buffer'
9
+
10
+ # HTML exporter
11
+ require 'org-ruby/html_output_buffer'
12
+ require 'org-ruby/html_symbol_replace'
13
+
14
+ # Textile exporter
15
+ require 'org-ruby/textile_output_buffer'
16
+ require 'org-ruby/textile_symbol_replace'
17
+
18
+ # Tilt support
19
+ require 'org-ruby/tilt'
7
20
 
8
21
  module OrgRuby
9
22
 
10
23
  # :stopdoc:
11
- VERSION = '0.6.1'
24
+ VERSION = '0.8.0'
12
25
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
13
26
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
14
27
  # :startdoc:
@@ -19,22 +32,6 @@ module OrgRuby
19
32
  VERSION
20
33
  end
21
34
 
22
- # Returns the library path for the module. If any arguments are given,
23
- # they will be joined to the end of the libray path using
24
- # <tt>File.join</tt>.
25
- #
26
- def self.libpath( *args )
27
- args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
28
- end
29
-
30
- # Returns the lpath for the module. If any arguments are given,
31
- # they will be joined to the end of the path using
32
- # <tt>File.join</tt>.
33
- #
34
- def self.path( *args )
35
- args.empty? ? PATH : ::File.join(PATH, args.flatten)
36
- end
37
-
38
35
  # Utility method used to require all files ending in .rb that lie in the
39
36
  # directory below this file that has the same name as the filename passed
40
37
  # in. Optionally, a specific _directory_ name can be passed in such that
@@ -48,8 +45,4 @@ module OrgRuby
48
45
  Dir.glob(search_me).sort.each {|rb| require rb}
49
46
  end
50
47
 
51
- end # module OrgmodeParser
52
-
53
- OrgRuby.require_all_libs_relative_to(__FILE__)
54
-
55
- end # unless defined?
48
+ end
@@ -1,5 +1,3 @@
1
- require OrgRuby.libpath(*%w[org-ruby line])
2
-
3
1
  module Orgmode
4
2
 
5
3
  # Represents a headline in an orgmode file.
@@ -47,7 +45,6 @@ module Orgmode
47
45
  def initialize(line, parser = nil, offset=0)
48
46
  super(line, parser)
49
47
  @body_lines = []
50
- @body_lines << self # Make @body_lines contain the headline?
51
48
  @tags = []
52
49
  @export_state = :exclude
53
50
  if (@line =~ LineRegexp) then
@@ -87,13 +84,6 @@ module Orgmode
87
84
  :"heading#{@level}"
88
85
  end
89
86
 
90
- # Converts this headline and its body to textile.
91
- def to_textile
92
- output = "h#{@level}. #{@headline_text}\n"
93
- output << Line.to_textile(@body_lines[1..-1])
94
- output
95
- end
96
-
97
87
  ######################################################################
98
88
  private
99
89
 
@@ -1,10 +1,12 @@
1
- require OrgRuby.libpath(*%w[org-ruby html_symbol_replace])
2
- require OrgRuby.libpath(*%w[org-ruby output_buffer])
3
-
4
1
  begin
5
- require 'coderay'
2
+ require 'pygments'
6
3
  rescue LoadError
7
- # CodeRay is not supported
4
+ # Pygments is not supported so we try instead with CodeRay
5
+ begin
6
+ require 'coderay'
7
+ rescue LoadError
8
+ # No code syntax highlighting
9
+ end
8
10
  end
9
11
 
10
12
  module Orgmode
@@ -13,12 +15,19 @@ module Orgmode
13
15
 
14
16
  HtmlBlockTag = {
15
17
  :paragraph => "p",
16
- :ordered_list => "li",
17
- :unordered_list => "li",
18
+ :ordered_list => "ol",
19
+ :unordered_list => "ul",
20
+ :list_item => "li",
21
+ :definition_list => "dl",
18
22
  :definition_term => "dt",
19
23
  :definition_descr => "dd",
24
+ :table => "table",
20
25
  :table_row => "tr",
21
- :table_header => "tr",
26
+ :quote => "blockquote",
27
+ :example => "pre",
28
+ :src => "pre",
29
+ :inline_example => "pre",
30
+ :center => "div",
22
31
  :heading1 => "h1",
23
32
  :heading2 => "h2",
24
33
  :heading3 => "h3",
@@ -27,18 +36,6 @@ module Orgmode
27
36
  :heading6 => "h6"
28
37
  }
29
38
 
30
- ModeTag = {
31
- :unordered_list => "ul",
32
- :ordered_list => "ol",
33
- :definition_list => "dl",
34
- :table => "table",
35
- :blockquote => "blockquote",
36
- :example => "pre",
37
- :src => "pre",
38
- :inline_example => "pre",
39
- :center => "div"
40
- }
41
-
42
39
  attr_reader :options
43
40
 
44
41
  def initialize(output, opts = {})
@@ -48,118 +45,160 @@ module Orgmode
48
45
  else
49
46
  @title_decoration = ""
50
47
  end
48
+ @buffer_tag = "HTML"
51
49
  @options = opts
50
+ @new_paragraph = :start
52
51
  @footnotes = {}
52
+ @unclosed_tags = []
53
53
  @logger.debug "HTML export options: #{@options.inspect}"
54
54
  end
55
55
 
56
56
  # Output buffer is entering a new mode. Use this opportunity to
57
- # write out one of the block tags in the ModeTag constant to put
58
- # this information in the HTML stream.
59
- def push_mode(mode)
60
- if ModeTag[mode] then
61
- output_indentation
62
- css_class = ""
63
- css_class = " class=\"src\"" if mode == :src
64
- css_class = " class=\"example\"" if (mode == :example || mode == :inline_example)
65
- css_class = " style=\"text-align: center\"" if mode == :center
66
- @logger.debug "#{mode}: <#{ModeTag[mode]}#{css_class}>\n"
67
- @output << "<#{ModeTag[mode]}#{css_class}>\n" unless mode == :table and skip_tables?
68
- # Special case to add code tags to src blogs and specify language
69
- if mode == :src
70
- @logger.debug "<code class=\"#{@block_lang}\">\n"
71
- @output << "<code class=\"#{@block_lang}\">\n"
57
+ # write out one of the block tags in the HtmlBlockTag constant to
58
+ # put this information in the HTML stream.
59
+ def push_mode(mode, indent)
60
+ super(mode)
61
+ @list_indent_stack.push(indent)
62
+
63
+ if HtmlBlockTag[mode]
64
+ unless ((mode_is_table?(mode) and skip_tables?) or
65
+ (mode == :src and defined? Pygments))
66
+ css_class = case
67
+ when (mode == :src and @block_lang.empty?)
68
+ " class=\"src\""
69
+ when (mode == :src and not @block_lang.empty?)
70
+ " class=\"src src-#{@block_lang}\""
71
+ when (mode == :example || mode == :inline_example)
72
+ " class=\"example\""
73
+ when mode == :center
74
+ " style=\"text-align: center\""
75
+ else
76
+ @title_decoration
77
+ end
78
+
79
+ add_paragraph unless @new_paragraph == :start
80
+ @new_paragraph = true
81
+
82
+ @logger.debug "#{mode}: <#{HtmlBlockTag[mode]}#{css_class}>"
83
+ @output << "<#{HtmlBlockTag[mode]}#{css_class}>"
84
+ # Entering a new mode obliterates the title decoration
85
+ @title_decoration = ""
72
86
  end
73
- # Entering a new mode obliterates the title decoration
74
- @title_decoration = ""
75
87
  end
76
- super(mode)
77
88
  end
78
89
 
79
90
  # We are leaving a mode. Close any tags that were opened when
80
91
  # entering this mode.
81
92
  def pop_mode(mode = nil)
82
93
  m = super(mode)
83
- if ModeTag[m] then
84
- output_indentation
85
- if mode == :src
86
- @logger.debug "</code>\n"
87
- @output << "</code>\n"
94
+ if HtmlBlockTag[m]
95
+ unless ((mode_is_table?(m) and skip_tables?) or
96
+ (m == :src and defined? Pygments))
97
+ add_paragraph if @new_paragraph
98
+ @new_paragraph = true
99
+ @logger.debug "</#{HtmlBlockTag[m]}>"
100
+ @output << "</#{HtmlBlockTag[m]}>"
88
101
  end
89
- @logger.debug "</#{ModeTag[m]}>\n"
90
- @output << "</#{ModeTag[m]}>\n" unless mode == :table and skip_tables?
91
102
  end
103
+ @list_indent_stack.pop
92
104
  end
93
105
 
94
106
  def flush!
95
- if mode_is_code(@buffer_mode) then
96
- # Only colorize #+BEGIN_SRC blocks with a specified language,
97
- # CodeRay already escapes the html once
98
- if @buffer_mode == :src and @block_lang != "" and defined?(CodeRay)
99
- @logger.debug "Applying syntax coloring for: #{@block_lang}"
107
+ return false if @buffer.empty?
108
+ case
109
+ when preserve_whitespace?
110
+ strip_code_block! if mode_is_code? current_mode
100
111
 
101
- # Also suppress CodeRay warning message when it cannot find the language alias
112
+ # NOTE: CodeRay and Pygments already escape the html once, so
113
+ # no need to escape_string!(@buffer)
114
+ case
115
+ when (current_mode == :src and defined? Pygments)
116
+ lang = normalize_lang @block_lang
117
+ @output << "\n" unless @new_paragraph == :start
118
+
119
+ begin
120
+ @buffer = Pygments.highlight(@buffer, :lexer => lang)
121
+ rescue
122
+ # Not supported lexer from Pygments, we fallback on using the text lexer
123
+ @buffer = Pygments.highlight(@buffer, :lexer => 'text')
124
+ end
125
+ when (current_mode == :src and defined? CodeRay)
126
+ lang = normalize_lang @block_lang
127
+
128
+ # CodeRay might throw a warning when unsupported lang is set,
129
+ # then fallback to using the text lexer
102
130
  silence_warnings do
103
- @buffer = CodeRay.scan(@buffer, @block_lang.to_s).html(:wrap => nil, :css => :style)
131
+ begin
132
+ @buffer = CodeRay.scan(@buffer, lang).html(:wrap => nil, :css => :style)
133
+ rescue ArgumentError
134
+ @buffer = CodeRay.scan(@buffer, 'text').html(:wrap => nil, :css => :style)
135
+ end
104
136
  end
137
+ when (current_mode == :html or current_mode == :raw_text)
138
+ @buffer.gsub!(/\A\n/, "") if @new_paragraph == :start
139
+ @new_paragraph = true
105
140
  else
106
- escape_buffer!
141
+ escape_string! @buffer
107
142
  end
108
143
 
109
- # Whitespace is significant in :code mode. Always output the buffer
110
- # and do not do any additional translation.
144
+ # Whitespace is significant in :code mode. Always output the
145
+ # buffer and do not do any additional translation.
111
146
  @logger.debug "FLUSH CODE ==========> #{@buffer.inspect}"
147
+ @output << @buffer
148
+
149
+ when (mode_is_table? current_mode and skip_tables?)
150
+ @logger.debug "SKIP ==========> #{current_mode}"
112
151
 
113
- @output << @buffer << "\n"
114
152
  else
115
- escape_buffer!
116
- if @buffer.length > 0 and @output_type == :definition_list then
117
- unless buffer_mode_is_table? and skip_tables?
118
- output_indentation
119
- d = @buffer.split("::", 2)
120
- @output << "<#{HtmlBlockTag[:definition_term]}#{@title_decoration}>" << inline_formatting(d[0].strip) \
121
- << "</#{HtmlBlockTag[:definition_term]}>"
122
- if d.length > 1 then
123
- @output << "<#{HtmlBlockTag[:definition_descr]}#{@title_decoration}>" << inline_formatting(d[1].strip) \
124
- << "</#{HtmlBlockTag[:definition_descr]}>\n"
125
- else
126
- @output << "\n"
127
- end
128
- @title_decoration = ""
129
- end
130
- elsif @buffer.length > 0 then
131
- unless buffer_mode_is_table? and skip_tables?
132
- @logger.debug "FLUSH ==========> #{@buffer_mode}"
133
- output_indentation
134
- @output << "<#{HtmlBlockTag[@output_type]}#{@title_decoration}>"
135
- if (@buffered_lines[0].kind_of?(Headline)) then
136
- headline = @buffered_lines[0]
137
- raise "Cannot be more than one headline!" if @buffered_lines.length > 1
138
- if @options[:export_heading_number] then
139
- level = headline.level
140
- heading_number = get_next_headline_number(level)
141
- output << "<span class=\"heading-number heading-number-#{level}\">#{heading_number} </span>"
142
- end
143
- if @options[:export_todo] and headline.keyword then
144
- keyword = headline.keyword
145
- output << "<span class=\"todo-keyword #{keyword}\">#{keyword} </span>"
146
- end
147
- end
148
- @output << inline_formatting(@buffer)
149
- @output << "</#{HtmlBlockTag[@output_type]}>\n"
150
- @title_decoration = ""
153
+ @buffer.lstrip!
154
+ @new_paragraph = nil
155
+ @logger.debug "FLUSH ==========> #{current_mode}"
156
+
157
+ case current_mode
158
+ when :definition_term
159
+ d = @buffer.split(/\A(.*[ \t]+|)::(|[ \t]+.*?)$/, 4)
160
+ d[1] = d[1].strip
161
+ unless d[1].empty?
162
+ @output << inline_formatting(d[1])
151
163
  else
152
- @logger.debug "SKIP ==========> #{@buffer_mode}"
164
+ @output << "???"
153
165
  end
166
+ indent = @list_indent_stack.last
167
+ pop_mode
168
+
169
+ @new_paragraph = :start
170
+ push_mode(:definition_descr, indent)
171
+ @output << inline_formatting(d[2].strip + d[3])
172
+ @new_paragraph = nil
173
+
174
+ when :horizontal_rule
175
+ add_paragraph unless @new_paragraph == :start
176
+ @new_paragraph = true
177
+ @output << "<hr />"
178
+
179
+ else
180
+ @output << inline_formatting(@buffer)
154
181
  end
155
182
  end
156
- clear_accumulation_buffer!
183
+ @buffer = ""
184
+ end
185
+
186
+ def add_line_attributes headline
187
+ if @options[:export_heading_number] then
188
+ level = headline.level
189
+ heading_number = get_next_headline_number(level)
190
+ @output << "<span class=\"heading-number heading-number-#{level}\">#{heading_number}</span> "
191
+ end
192
+ if @options[:export_todo] and headline.keyword then
193
+ keyword = headline.keyword
194
+ @output << "<span class=\"todo-keyword #{keyword}\">#{keyword}</span> "
195
+ end
157
196
  end
158
197
 
159
198
  def output_footnotes!
160
199
  return false unless @options[:export_footnotes] and not @footnotes.empty?
161
200
 
162
- @output << "<div id=\"footnotes\">\n<h2 class=\"footnotes\">Footnotes: </h2>\n<div id=\"text-footnotes\">\n"
201
+ @output << "\n<div id=\"footnotes\">\n<h2 class=\"footnotes\">Footnotes:</h2>\n<div id=\"text-footnotes\">\n"
163
202
 
164
203
  @footnotes.each do |name, defi|
165
204
  @output << "<p class=\"footnote\"><sup><a class=\"footnum\" name=\"fn.#{name}\" href=\"#fnr.#{name}\">#{name}</a></sup>" \
@@ -167,11 +206,15 @@ module Orgmode
167
206
  << "</p>\n"
168
207
  end
169
208
 
170
- @output << "</div>\n</div>\n"
209
+ @output << "</div>\n</div>"
171
210
 
172
211
  return true
173
212
  end
174
213
 
214
+ # Test if we're in an output mode in which whitespace is significant.
215
+ def preserve_whitespace?
216
+ super or current_mode == :html
217
+ end
175
218
 
176
219
  ######################################################################
177
220
  private
@@ -180,84 +223,116 @@ module Orgmode
180
223
  @options[:skip_tables]
181
224
  end
182
225
 
183
- def buffer_mode_is_table?
184
- @buffer_mode == :table
226
+ def mode_is_table?(mode)
227
+ (mode == :table or mode == :table_row or
228
+ mode == :table_separator or mode == :table_header)
185
229
  end
186
230
 
187
231
  # Escapes any HTML content in the output accumulation buffer @buffer.
188
- def escape_buffer!
189
- @buffer.gsub!(/&/, "&amp;")
190
- @buffer.gsub!(/</, "&lt;")
191
- @buffer.gsub!(/>/, "&gt;")
232
+ def escape_string! str
233
+ str.gsub!(/&/, "&amp;")
234
+ # Escapes the left and right angular brackets but construction
235
+ # @<text> which is formatted to <text>
236
+ str.gsub! /<([^<>\n]*)/ do |match|
237
+ if $`[-1..-1] == "@" and $'[0..0] == ">" then $&
238
+ else "&lt;#{$1}"
239
+ end
240
+ end
241
+ str.gsub! /([^<>\n]*)>/ do |match|
242
+ if $`[-2..-1] == "@<" then $&
243
+ else "#{$1}&gt;"
244
+ end
245
+ end
246
+ str.gsub!(/@(<[^<>\n]*>)/, "\\1")
192
247
  end
193
248
 
194
- def output_indentation
195
- indent = " " * (@mode_stack.length - 1)
196
- @output << indent
249
+ def buffer_indentation
250
+ indent = " " * @list_indent_stack.length
251
+ @buffer << indent
252
+ end
253
+
254
+ def add_paragraph
255
+ indent = " " * (@list_indent_stack.length - 1)
256
+ @output << "\n" << indent
197
257
  end
198
258
 
199
259
  Tags = {
200
- "*" => { :open => "<b>", :close => "</b>" },
201
- "/" => { :open => "<i>", :close => "</i>" },
202
- "_" => { :open => "<span style=\"text-decoration:underline;\">",
203
- :close => "</span>" },
204
- "=" => { :open => "<code>", :close => "</code>" },
205
- "~" => { :open => "<code>", :close => "</code>" },
206
- "+" => { :open => "<del>", :close => "</del>" }
260
+ "*" => { :open => "b", :close => "b" },
261
+ "/" => { :open => "i", :close => "i" },
262
+ "_" => { :open => "span style=\"text-decoration:underline;\"",
263
+ :close => "span" },
264
+ "=" => { :open => "code", :close => "code" },
265
+ "~" => { :open => "code", :close => "code" },
266
+ "+" => { :open => "del", :close => "del" }
207
267
  }
208
268
 
209
269
  # Applies inline formatting rules to a string.
210
270
  def inline_formatting(str)
211
- str.rstrip!
212
- str = @re_help.rewrite_emphasis(str) do |marker, s|
213
- "#{Tags[marker][:open]}#{s}#{Tags[marker][:close]}"
271
+ @re_help.rewrite_emphasis str do |marker, s|
272
+ "@<#{Tags[marker][:open]}>#{s}@</#{Tags[marker][:close]}>"
214
273
  end
215
274
  if @options[:use_sub_superscripts] then
216
- str = @re_help.rewrite_subp(str) do |type, text|
275
+ @re_help.rewrite_subp str do |type, text|
217
276
  if type == "_" then
218
- "<sub>#{text}</sub>"
277
+ "@<sub>#{text}@</sub>"
219
278
  elsif type == "^" then
220
- "<sup>#{text}</sup>"
279
+ "@<sup>#{text}@</sup>"
221
280
  end
222
281
  end
223
282
  end
224
- str = @re_help.rewrite_images(str) do |link|
225
- "<a href=\"#{link}\"><img src=\"#{link}\" /></a>"
226
- end
227
- str = @re_help.rewrite_links(str) do |link, text|
228
- text ||= link
229
- link = link.sub(/^file:(.*)::(.*?)$/) do
230
-
283
+ @re_help.rewrite_links str do |link, defi|
284
+ [link, defi].compact.each do |text|
231
285
  # We don't support search links right now. Get rid of it.
286
+ text.sub!(/\A(file:[^\s]+)::[^\s]*?\Z/, "\\1")
287
+ text.sub!(/\A(file:[^\s]+)\.org\Z/i, "\\1.html")
288
+ text.sub!(/\Afile:(?=[^\s]+\Z)/, "")
289
+ end
290
+
291
+ # We don't add a description for images in links, because its
292
+ # empty value forces the image to be inlined.
293
+ defi ||= link unless link =~ @re_help.org_image_file_regexp
232
294
 
233
- "file:#{$1}"
295
+ if defi =~ @re_help.org_image_file_regexp
296
+ defi = "@<img src=\"#{defi}\" alt=\"#{defi}\" />"
234
297
  end
235
- link = link.sub(/^file:/i, "") # will default to HTTP
236
- link = link.sub(/\.org$/i, ".html")
237
- text = text.gsub(/([^\]]*\.(jpg|jpeg|gif|png))/xi) do |img_link|
238
- "<img src=\"#{img_link}\" />"
298
+
299
+ if defi
300
+ "@<a href=\"#{link}\">#{defi}@</a>"
301
+ else
302
+ "@<img src=\"#{link}\" alt=\"#{link}\" />"
239
303
  end
240
- "<a href=\"#{link}\">#{text}</a>"
241
304
  end
242
- if (@output_type == :table_row) then
243
- str.gsub!(/^\|\s*/, "<td>")
244
- str.gsub!(/\s*\|$/, "</td>")
245
- str.gsub!(/\s*\|\s*/, "</td><td>")
305
+ if @output_type == :table_row
306
+ str.gsub!(/^\|\s*/, "@<td>")
307
+ str.gsub!(/\s*\|$/, "@</td>")
308
+ str.gsub!(/\s*\|\s*/, "@</td>@<td>")
246
309
  end
247
- if (@output_type == :table_header) then
248
- str.gsub!(/^\|\s*/, "<th>")
249
- str.gsub!(/\s*\|$/, "</th>")
250
- str.gsub!(/\s*\|\s*/, "</th><th>")
310
+ if @output_type == :table_header
311
+ str.gsub!(/^\|\s*/, "@<th>")
312
+ str.gsub!(/\s*\|$/, "@</th>")
313
+ str.gsub!(/\s*\|\s*/, "@</th>@<th>")
251
314
  end
252
315
  if @options[:export_footnotes] then
253
- str = @re_help.rewrite_footnote(str) do |name, defi|
316
+ @re_help.rewrite_footnote str do |name, defi|
254
317
  # TODO escape name for url?
255
318
  @footnotes[name] = defi if defi
256
- "<sup><a class=\"footref\" name=\"fnr.#{name}\" href=\"#fn.#{name}\">#{name}</a></sup>"
319
+ "@<sup>@<a class=\"footref\" name=\"fnr.#{name}\" href=\"#fn.#{name}\">#{name}@</a>@</sup>"
257
320
  end
258
321
  end
259
- Orgmode.special_symbols_to_html(str)
260
- str
322
+ escape_string! str
323
+ Orgmode.special_symbols_to_html str
324
+ str = @re_help.restore_code_snippets str
325
+ end
326
+
327
+ def normalize_lang(lang)
328
+ case lang
329
+ when 'emacs-lisp', 'common-lisp', 'lisp'
330
+ 'scheme'
331
+ when ''
332
+ 'text'
333
+ else
334
+ lang
335
+ end
261
336
  end
262
337
 
263
338
  # Helper method taken from Rails
@@ -269,5 +344,11 @@ module Orgmode
269
344
  ensure
270
345
  $VERBOSE = warn_level
271
346
  end
347
+
348
+ def strip_code_block!
349
+ strip_regexp = Regexp.new("^" + " " * @code_block_indent)
350
+ @buffer.gsub!(strip_regexp, "")
351
+ @code_block_indent = nil
352
+ end
272
353
  end # class HtmlOutputBuffer
273
354
  end # module Orgmode