org 2009.03.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ [96fa8b5 | Sat Mar 28 06:57:31 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
2
+
3
+ * Better rake tasks, now managed by raku
4
+
5
+ [971a989 | Fri Mar 20 05:23:05 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
6
+
7
+ * Spec how lists behave right now
8
+
9
+ [c21d3fb | Sun Mar 15 06:39:58 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
10
+
11
+ * Fix the header spec
12
+
13
+ [93db8d3 | Sun Mar 15 06:35:43 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
14
+
15
+ * Transform input to use \n, add specs for it
16
+
17
+ [9b1ff3a | Sat Feb 21 04:49:40 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
18
+
19
+ * Fix gemspec
20
+
21
+ [bca87be | Sat Feb 21 04:47:40 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
22
+
23
+ * Add the Rakefile
24
+
25
+ [f304ebf | Sat Feb 21 03:40:35 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
26
+
27
+ * Version 2009.02.21
28
+
29
+ [ca4d900 | Thu Jan 01 14:55:47 UTC 2009] Michael Fellinger <m.fellinger@gmail.com>
30
+
31
+ * Org for rakki
32
+
33
+ [3b1f2d2 | Sun Oct 12 08:22:45 UTC 2008] Michael Fellinger <m.fellinger@gmail.com>
34
+
35
+ * Extracted from rakki
36
+
@@ -0,0 +1,29 @@
1
+ CHANGELOG
2
+ MANIFEST
3
+ README.md
4
+ Rakefile
5
+ doc/syntax.org
6
+ lib/org.rb
7
+ lib/org/markup.rb
8
+ lib/org/rule.rb
9
+ lib/org/rules.rb
10
+ lib/org/scope.rb
11
+ lib/org/scope/org_mode.rb
12
+ lib/org/state.rb
13
+ lib/org/stringscanner.rb
14
+ lib/org/to/html.rb
15
+ lib/org/to/toc.rb
16
+ lib/org/token.rb
17
+ lib/org/version.rb
18
+ org.gemspec
19
+ spec/org.rb
20
+ tasks/bacon.rake
21
+ tasks/changelog.rake
22
+ tasks/gem.rake
23
+ tasks/gem_installer.rake
24
+ tasks/grancher.rake
25
+ tasks/install_dependencies.rake
26
+ tasks/manifest.rake
27
+ tasks/rcov.rake
28
+ tasks/release.rake
29
+ tasks/reversion.rake
@@ -0,0 +1,26 @@
1
+ # Org
2
+
3
+ Org provides transformation of a selected subset of org-mode markup for wikis.
4
+
5
+ ## About
6
+
7
+ If you fancy emacs' org-mode and would like to use its power for a wiki based on plain-text files you should check this out.
8
+ Org tries to stay compatible with org-mode, but does not support the full syntax. The most notable features you will find are table of contents, tables, headers, links and simple physical text formatting.
9
+ One feature org-mode doesn't provide (AFAIK) is code highlighting, since the preferred way is to simply link to the file containing the code, but that is a bit impractical in a wiki, so I added this feature.
10
+
11
+ ## Features
12
+
13
+ * Headers
14
+ * Links
15
+ * Tables
16
+ * Text markup
17
+
18
+ ## Dependencies
19
+
20
+ * StringScanner (ruby stdlib)
21
+ * CodeRay (optional)
22
+ * Uv (optional)
23
+
24
+ ## Syntax
25
+
26
+ For a nice intro to the syntax supported by Org please check the [doc/syntax.org] file.
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/gempackagetask'
4
+ require 'time'
5
+ require 'date'
6
+
7
+ PROJECT_SPECS = Dir['spec/**/*.rb']
8
+ PROJECT_MODULE = 'Org'
9
+
10
+ GEMSPEC = Gem::Specification.new{|s|
11
+ s.name = 'org'
12
+ s.author = "Michael 'manveru' Fellinger"
13
+ s.summary = "transformation of a subset of org-mode markup to html."
14
+ s.description = "transformation of a subset of org-mode markup to html."
15
+ s.email = 'm.fellinger@gmail.com'
16
+ s.homepage = 'http://github.com/manveru/org'
17
+ s.platform = Gem::Platform::RUBY
18
+ s.version = (ENV['PROJECT_VERSION'] || Date.today.strftime("%Y.%m.%d"))
19
+ s.files = `git ls-files`.split("\n").sort
20
+ s.has_rdoc = true
21
+ s.require_path = 'lib'
22
+ }
23
+
24
+ Dir['tasks/*.rake'].each{|f| import(f) }
25
+
26
+ task :default => [:bacon]
27
+
28
+ CLEAN.include('')
@@ -0,0 +1,73 @@
1
+ * OrgMarkup
2
+
3
+ ** Links
4
+
5
+ Internal Links follow the [[Wiki]] [[Wiki][Wiki Wiki]] style, also WikiWords work.
6
+
7
+ To recap:
8
+
9
+ [[Wiki]] is `[[Wiki]]`
10
+ [[Wiki][Wiki]] is `[[Wiki][Wiki]]`
11
+ WikiWords was `WikiWords`
12
+
13
+ You can easily plug into the handling of links and implement things like `[[flash:screencast-blog][My Screencast about Blogging]]`, but by default there will be no link formatting until I can find a nice set of defaults.
14
+
15
+ ** Lists
16
+
17
+ * Lists start with a `*` after one or more spaces from the beginning of a line.
18
+ * Nested lists are maybe not working correctly yet.
19
+
20
+ ** Headers
21
+
22
+ Headers are written as follows:
23
+
24
+ {{{
25
+ * h1
26
+ ** h2
27
+ *** h3
28
+ **** h4
29
+ ***** h5
30
+ ****** h6
31
+ }}}
32
+
33
+ ** Code
34
+
35
+ You can start a code block with `{{{` and end it with `}}}`, each on its own line. For code inside a line please use =`backticks`=.
36
+
37
+ {{{
38
+ This is a line of code
39
+ }}}
40
+
41
+
42
+ {{{ ruby
43
+ puts "This is a line of Ruby code"
44
+ }}}
45
+
46
+ You may also use `c`, `delphi`, `html`, `ezamar`, `nitro_xhtml`, `plaintext`, `rhtml`, or `xml`
47
+
48
+ ** Text formatting
49
+
50
+ /italic/ is `/italic/`
51
+ *bold* is `*bold*`
52
+ _underline_ is `_underline_`
53
+ +strikethrough+ is `+strikethrough+`
54
+ ~blockquote~ is `~blockquote~`
55
+ =code= is `=code=`
56
+ and `code` is =`code`=
57
+ last, but not least, there's also `----` the horizontal rule
58
+
59
+ ----
60
+
61
+ ** Tables
62
+
63
+ |--------------+-------------------------+----------------|
64
+ | Name | Telephone | Room |
65
+ |--------------+-------------------------+----------------|
66
+ | Mr. X | 777-777 | 42 |
67
+ | Mrs. Y | 888-888 | 21 |
68
+ | see? | tables | are |
69
+ | easy | enough | eh? |
70
+ |--------------+-------------------------+----------------|
71
+ | you can even | use separating elements | but they won't |
72
+ | show up | in the | endresult. |
73
+ |--------------+-------------------------+----------------|
@@ -0,0 +1,28 @@
1
+ require 'strscan'
2
+ require 'pp'
3
+
4
+ $LOAD_PATH.unshift File.dirname(__FILE__)
5
+
6
+ module Org
7
+ module_function
8
+
9
+ def escape_html(string)
10
+ string.to_s.gsub("&", "&amp;").
11
+ gsub("<", "&lt;").
12
+ gsub(">", "&gt;").
13
+ gsub("'", "&#39;").
14
+ gsub('"', "&quot;")
15
+ end
16
+ end
17
+
18
+ require 'org/version'
19
+ require 'org/stringscanner'
20
+ require 'org/markup'
21
+ require 'org/state'
22
+ require 'org/scope'
23
+ require 'org/token'
24
+ require 'org/rule'
25
+
26
+ require 'org/scope/org_mode'
27
+ require 'org/to/html'
28
+ require 'org/to/toc'
@@ -0,0 +1,34 @@
1
+ module Org
2
+ class Markup
3
+ attr_accessor :string
4
+
5
+ def initialize(file = nil)
6
+ self.string = File.read(file) if file
7
+ end
8
+
9
+ def apply(string = @string)
10
+ self.string = string
11
+
12
+ parent = RootToken.new(:root, nil)
13
+ scanner = StringScanner.new(self.string)
14
+ state = State.new(@scope, parent, scanner)
15
+
16
+ until scanner.eos?
17
+ pos = scanner.pos
18
+ state.step
19
+ raise("Didn't move: %p" % scanner) if pos == scanner.pos
20
+ end
21
+
22
+ return parent
23
+ end
24
+
25
+ def scope(name, options = {}, &block)
26
+ @scope = Scope.new(name, options)
27
+ yield(@scope)
28
+ end
29
+
30
+ def string=(string)
31
+ @string = string.gsub(/\r\n|\r/, "\n")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ module Org
2
+ class Rule
3
+ DEFAULT = {
4
+ :bol => false,
5
+ :start => nil,
6
+ :end => nil,
7
+ :unscan => false,
8
+ }
9
+
10
+ attr_accessor :name, :regex
11
+
12
+ def initialize(name, regex, options = {}, &block)
13
+ @name, @regex, @block = name, regex, block
14
+ @options = DEFAULT.merge(options)
15
+ end
16
+
17
+ def match(state)
18
+ scope, parent, scanner = state.scope, state.parent, state.scanner
19
+ return if @options[:bol] and not scanner.bol?
20
+
21
+ return false unless scanner.scan(@regex)
22
+ scanner.unscan if @options[:unscan]
23
+
24
+ name = @options[:tag] || @name
25
+ token = Token.new(name, scanner.captures, &@block)
26
+ return true if @options[:ignore]
27
+
28
+ if mode = @options[:start]
29
+ # puts "Start #{mode}"
30
+ state.scope = mode.is_a?(Scope) ? mode : scope.scopes[mode]
31
+ parent << token
32
+ state.parent = token
33
+ elsif mode = @options[:end]
34
+ # puts "End #{mode}"
35
+ state.parent = parent.parent
36
+ state.scope = scope.parent
37
+ else
38
+ parent << token
39
+ return true
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,108 @@
1
+ require 'org'
2
+
3
+ # rs = RuleSet.new("~/c/innate/example/app/wiki/pages/Home.owl")
4
+ rs = OrgMarkup.new("test.org")
5
+
6
+ rs.scope(:block, :indent => true) do |block|
7
+ block.rule :header, /(\*+)\s+(.*)\n/, :bol => true
8
+ block.rule :table, /\|([^|]+)/, :bol => true, :start => :table, :unscan => true
9
+ block.rule :br, /\n/
10
+ block.rule :p, /(.)/, :bol => true, :start => :inline, :unscan => true
11
+ block.rule :space, /\s/
12
+
13
+ inline_rules = lambda do |parent|
14
+ # * You can make words *bold*, /italic/, _underlined_, `=code=' and
15
+ # `~verbatim~', and, if you must, `+strikethrough+'. Text in the
16
+ # code and verbatim string is not processed for org-mode specific
17
+ # syntax, it is exported verbatim.
18
+ parent.rule :a, /\b([A-Z]\w+[A-Z]\w+)/
19
+ parent.rule :text, /([A-Za-z0-9,. ]+)/
20
+ # [[file:foo][My file foo]]
21
+ parent.rule :a, /\[\[([^:\]]+):([^\]]+)\]\[([^\]]+)\]\]/
22
+ # [[http://go.to/][Go to]]
23
+ parent.rule :a, /\[\[([^\]]+)\]\[([^\]]+)\]\]/
24
+ # [[file:foo]]
25
+ parent.rule :a, /\[\[([^:\]]+):([^\]]+)\]\]/
26
+ # [[foo]]
27
+ parent.rule :a, /\[\[([^\]]+)\]\]/
28
+ parent.rule :italic, /\/([^\/]+)\//
29
+ parent.rule :bold, /\*([^*]+)\*/, :tag => :b
30
+ parent.rule :underline, /_([^_]+)_/
31
+ parent.rule :strikethrough, /\+([^+]+)\+/
32
+ parent.rule :verbatim, /~([^~]+)~/
33
+ parent.rule :code, /\=([^=]+)\=/
34
+ end
35
+
36
+ block.scope(:inline, :indent => false) do |inline|
37
+ inline.apply(&inline_rules)
38
+ inline.rule :text, /(.)/
39
+ inline.rule :close, /\n\n+/, :end => :inline
40
+ inline.rule :br, /\n/
41
+ end
42
+
43
+ block.scope(:table, :indent => true) do |table|
44
+ # | name | telelphone | room |
45
+ # |--------+------------+------|
46
+ # | Mr. X | 777-777 | 42 |
47
+ # | Mrs. Y | 888-888 | 21 |
48
+
49
+ table.rule :tr, /\|([^|]+)/, :bol => true, :unscan => true, :start => :tr
50
+ table.rule :close, /\n/, :end => :table
51
+
52
+ table.scope(:tr, :indent => true) do |tr|
53
+ tr.rule :table_separator, /\|[+-]+\|/
54
+ tr.rule :close, /\|\n/, :end => :tr
55
+ tr.rule :close, /\n/, :end => :tr
56
+ tr.rule :td, /\|/, :start => :td
57
+
58
+ tr.scope :td do |td|
59
+ td.apply(&inline_rules)
60
+ td.rule :space, /([\t ]+)/
61
+ td.rule :text, /([^|])/
62
+ td.rule :close, /\|/, :end => :td, :unscan => true
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ require 'pp'
69
+
70
+ class OrgMarkup
71
+ module ToHtml
72
+ def html_link(leader, href = nil, title = nil)
73
+ case leader
74
+ when 'rss'
75
+ link_rss(href, title)
76
+ when 'file'
77
+ link_file(href, title)
78
+ when 'http', 'https', 'ftp'
79
+ link_out("#{leader}:#{href}", title)
80
+ else
81
+ link_in(leader, href)
82
+ end
83
+ end
84
+
85
+ # Respond to [[rss:href]] and [[rss:href][title]]
86
+ def link_rss(href, title)
87
+ "<rss %p %p>" % [href, title]
88
+ ''
89
+ end
90
+
91
+ # Respond to [[file:href]] and [[file:href][title]]
92
+ def link_file(href, title)
93
+ "<file %p %p>" % [href, title]
94
+ ''
95
+ end
96
+
97
+ def link_out(href, title)
98
+ "<out %p %p>" % [href, title]
99
+ tag(:a, title || href, :href => href)
100
+ end
101
+
102
+ # Respond to [[name]] and [[name][title]]
103
+ def link_in(href, title)
104
+ "<wiki %p %p>" % [href, title]
105
+ tag(:a, title || href, :href => "/#{href}")
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,35 @@
1
+ module Org
2
+ class Scope
3
+ attr_accessor :parent, :name, :scopes
4
+
5
+ def initialize(name, options = {})
6
+ @rules = []
7
+ @name, @options = name, options
8
+ @scopes = {}
9
+ end
10
+
11
+ def scope(name, options = {}, &block)
12
+ scope = Scope.new(name, options)
13
+ scope.parent = self
14
+ yield @scopes[name] = scope
15
+ end
16
+
17
+ def rule(name, regex, options = {})
18
+ @rules << Rule.new(name, regex, options)
19
+ end
20
+
21
+ def apply
22
+ yield(self)
23
+ end
24
+
25
+ def step(state)
26
+ @rules.find do |rule|
27
+ rule.match(state)
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ "<Scope #{name}>"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,93 @@
1
+ module Org
2
+ OrgMode = Markup.new
3
+ eol = /\n/ # we keep this simple and convert the input string instead
4
+
5
+ OrgMode.scope(:block, :indent => true) do |block|
6
+ block.rule :header, /(\*+)\s+(.*)(#{eol}|\z)/, :bol => true
7
+ block.rule :table, /\|([^|]+)/, :bol => true, :start => :table, :unscan => true
8
+ block.rule :ul, /[ \t]+[\*\+\-]+\s*(.*)/, :start => :ul, :unscan => true, :bol => true
9
+ block.rule :ol, /[ \t]+[0-9]+[\.\)]\s*(.*)/, :start => :ol, :unscan => true, :bol => true
10
+ block.rule :br, eol
11
+ block.rule :p, /(.)/, :bol => true, :start => :inline, :unscan => true
12
+ block.rule :space, /\s/
13
+
14
+ inline_rules = lambda do |parent|
15
+ # * You can make words *bold*, /italic/, _underlined_, `=code=' and
16
+ # `~verbatim~', and, if you must, `+strikethrough+'. Text in the
17
+ # code and verbatim string is not processed for org-mode specific
18
+ # syntax, it is exported verbatim.
19
+ parent.rule :a, /\b([A-Z]\w+[A-Z]\w+)/
20
+ parent.rule :text, /([A-Za-z0-9,. ]+)/
21
+ # parent.rule :text, /(\/\/)/
22
+ parent.rule :a, /\[\[([^\]]+)\]\[([^\]]+)\]\]/
23
+ parent.rule :a, /\[\[(.+?)\]\]/
24
+ parent.rule :italic, /\/([^\/ ]+)\//, :tag => :i
25
+ parent.rule :bold, /\*([^* ]+)\*/, :tag => :b
26
+ parent.rule :underline, /_([^_ ]+)_/, :tag => :u
27
+ parent.rule :strikethrough, /\+([^+ ]+)\+/, :tag => :s
28
+ parent.rule :blockquote, /~([^~ ]+)~/
29
+ parent.rule :code, /\=([^= ]+)\=/
30
+ parent.rule :code, /`([^`]+)`/
31
+ parent.rule :hr, /---+/, :bol => true
32
+ end
33
+
34
+ block.scope :ul do |ul|
35
+ ul.rule :li, /[ \t]+[\*\+\-]+\s*/, :start => :li, :bol => true
36
+ ul.rule :close, eol, :end => :ul
37
+ ul.rule :close, /(.)/, :end => :ul, :unscan => true
38
+
39
+ ul.scope :li do |li|
40
+ li.apply(&inline_rules)
41
+ li.rule :text, /(.)/
42
+ li.rule :ul, /[ \t]+[\*\+\-]+\s*/, :start => ul, :bol => true
43
+ li.rule :close, eol, :end => :li
44
+ end
45
+ end
46
+
47
+ block.scope :ol do |ol|
48
+ ol.rule :li, /[ \t]+[0-9]+[\.\)]\s*/, :start => :li, :bol => true
49
+ # ol.rule :ul, /[ \t]+[\*\-\+]+\s*/, :start => :ul, :bol => true, :unscan => true
50
+ ol.rule :close, eol, :end => :ol
51
+ ol.rule :close, /(.)/, :end => :ol, :unscan => true
52
+
53
+ ol.scope :li do |li|
54
+ li.apply(&inline_rules)
55
+ li.rule :text, /(.)/
56
+ li.rule :close, eol, :end => :li
57
+ end
58
+ end
59
+
60
+ block.scope(:inline, :indent => false) do |inline|
61
+ inline.apply(&inline_rules)
62
+ inline.rule :highlight, /\{\{\{[\t ]*(\S+)#{eol}(.*?)#{eol}\}\}\}/m
63
+ inline.rule :highlight, /\{\{\{#{eol}(.*?)#{eol}\}\}\}/m
64
+ inline.rule :text, /(.)/
65
+ inline.rule :close, /#{eol}#{eol}+/, :end => :inline
66
+ inline.rule :br, eol
67
+ end
68
+
69
+ block.scope(:table, :indent => true) do |table|
70
+ # | name | telelphone | room |
71
+ # |--------+------------+------|
72
+ # | Mr. X | 777-777 | 42 |
73
+ # | Mrs. Y | 888-888 | 21 |
74
+
75
+ table.rule :tr, /\|([^|]+)/, :bol => true, :unscan => true, :start => :tr
76
+ table.rule :close, eol, :end => :table
77
+
78
+ table.scope(:tr, :indent => true) do |tr|
79
+ tr.rule :table_separator, /\|[+-]+\|/, :ignore => true
80
+ tr.rule :close, /\|#{eol}/, :end => :tr
81
+ tr.rule :close, eol, :end => :tr
82
+ tr.rule :td, /\|/, :start => :td
83
+
84
+ tr.scope :td do |td|
85
+ td.apply(&inline_rules)
86
+ td.rule :space, /([\t ]+)/
87
+ td.rule :text, /([^|])/
88
+ td.rule :close, /\|/, :end => :td, :unscan => true
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,12 @@
1
+ module Org
2
+ class State < Struct.new(:scope, :parent, :scanner)
3
+ def step
4
+ loop do
5
+ # before = scanner.string[0...scanner.pos][-25, 25]
6
+ # after = scanner.string[scanner.pos..-1][0, 50]
7
+ # p "%40s@%40s" % [before, after]
8
+ break unless scope.step(self)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'strscan'
2
+
3
+ module Org
4
+ # Adding some comfort
5
+ class StringScanner < ::StringScanner
6
+ # Equivalent to Regexp#captures, returns Array of all matches
7
+ def captures
8
+ n = 0
9
+ found = []
10
+ while n += 1
11
+ return found unless element = self[n]
12
+ found << element
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,91 @@
1
+ module Org
2
+ class RootToken < Token
3
+ # little optimization, avoid check for root
4
+ def to_html
5
+ @childs.map{|child| child.to_html }.join
6
+ end
7
+ end
8
+
9
+ module ToHtml
10
+ def to_html
11
+ method = "html_#{@name}"
12
+
13
+ if respond_to?(method)
14
+ send(method)
15
+ elsif @childs.empty?
16
+ Tag.new(name, values)
17
+ else
18
+ Tag.new(name, values){ @childs.map{|c| c.to_html }.join }
19
+ end
20
+ end
21
+
22
+ def html_text
23
+ Org.escape_html(values.join)
24
+ end
25
+
26
+ # unify toc_id somwhere?
27
+ def html_header
28
+ level, text = values[0].size, values[1]
29
+ id = respond_to?(:toc_id) ? toc_id : text.gsub(/\W/, '-').squeeze('-').downcase
30
+ Tag.new("h#{level}", text, :id => id)
31
+ end
32
+
33
+ def html_space
34
+ ' '
35
+ end
36
+
37
+ # TODO: find a simple way of caching highlighted code from Uv,
38
+ # gives us much more possibilities in highlighting compared
39
+ # to coderay, but is also _really_ slow.
40
+ def html_highlight
41
+ language, code = *values
42
+ require 'coderay'
43
+ language = 'nitro_xhtml' if language == 'ezamar'
44
+
45
+ case language
46
+ when *%w[ruby c delphi html nitro_xhtml plaintext rhtml xml]
47
+ tokens = CodeRay.scan(code, language)
48
+ html = tokens.html(:wrap => :div)
49
+ when *%w[diff]
50
+ require 'uv'
51
+ Uv.parse(code, output = 'xhtml', syntax_name = language, line_numbers = false, render_style = 'amy', headers = false)
52
+ else
53
+ code = language if not code or code.strip.empty?
54
+ html = tag(:pre, code)
55
+ end
56
+ end
57
+
58
+ def tag(*args)
59
+ Tag.new(*args)
60
+ end
61
+ end
62
+
63
+ # Extracted from Ramaze Gestalt
64
+ class Tag
65
+ def initialize(name, value, args = {}, &block)
66
+ @name, @value, @args, @block = name, value, args, block
67
+ end
68
+
69
+ def to_s
70
+ @out = ''
71
+ build_tag(@name, @args, @value, &@block)
72
+ @out
73
+ end
74
+
75
+ def build_tag(name, attr = {}, text = [])
76
+ @out << "<#{name}"
77
+ @out << attr.map{|k,v| %[ #{k}="#{Org.escape_html(v)}"] }.join
78
+ if text != [] or block_given?
79
+ @out << ">"
80
+ @out << Org.escape_html([text].join)
81
+ if block_given?
82
+ text = yield
83
+ @out << text.to_str if text != @out and text.respond_to?(:to_str)
84
+ end
85
+ @out << "</#{name}>"
86
+ else
87
+ @out << ' />'
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,51 @@
1
+ module Org
2
+ class RootToken
3
+ def to_toc
4
+ found = @childs.map{|child| child.to_toc }.flatten.compact
5
+
6
+ out = []
7
+ nest = 0
8
+
9
+ while token = found.shift
10
+ level, text = *token.values
11
+ level = level.size
12
+
13
+ if level > nest
14
+ out << '<ol>'
15
+ elsif level < nest
16
+ out << '</ol>'
17
+ end
18
+ nest = level
19
+
20
+ out << "<li>#{token.toc_link}</li>"
21
+ end
22
+
23
+ nest.times do
24
+ out << '</ol>'
25
+ end
26
+
27
+ out
28
+ end
29
+ end
30
+
31
+ module ToToc
32
+ TOC_ENTRIES = [:header]
33
+
34
+ def to_toc
35
+ case @name
36
+ when *TOC_ENTRIES
37
+ self
38
+ else
39
+ @childs.map{|child| child.to_toc }
40
+ end
41
+ end
42
+
43
+ def toc_link
44
+ tag(:a, values[1], :href => "##{toc_id}")
45
+ end
46
+
47
+ def toc_id
48
+ values[1].gsub(/\W/, '-').squeeze('-').downcase
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ module Org
2
+ class Token
3
+ attr_accessor :name, :values, :options, :block, :childs, :parent
4
+
5
+ def initialize(name, values, options = {}, &block)
6
+ @name, @values, @options, @block = name, values, options, block
7
+ @childs = []
8
+ end
9
+
10
+ def <<(token)
11
+ token.parent = self
12
+ @childs << token
13
+ end
14
+
15
+ def pretty_inspect
16
+ {[name, values] => childs}.pretty_inspect
17
+ end
18
+ alias inspect pretty_inspect
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Org
2
+ VERSION = "2009.03.28"
3
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{org}
5
+ s.version = "2009.03.28"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Michael 'manveru' Fellinger"]
9
+ s.date = %q{2009-03-28}
10
+ s.description = %q{transformation of a subset of org-mode markup to html.}
11
+ s.email = %q{m.fellinger@gmail.com}
12
+ s.files = ["CHANGELOG", "MANIFEST", "README.md", "Rakefile", "doc/syntax.org", "lib/org.rb", "lib/org/markup.rb", "lib/org/rule.rb", "lib/org/rules.rb", "lib/org/scope.rb", "lib/org/scope/org_mode.rb", "lib/org/state.rb", "lib/org/stringscanner.rb", "lib/org/to/html.rb", "lib/org/to/toc.rb", "lib/org/token.rb", "lib/org/version.rb", "org.gemspec", "spec/org.rb", "tasks/bacon.rake", "tasks/changelog.rake", "tasks/gem.rake", "tasks/gem_installer.rake", "tasks/grancher.rake", "tasks/install_dependencies.rake", "tasks/manifest.rake", "tasks/rcov.rake", "tasks/release.rake", "tasks/reversion.rake"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://github.com/manveru/org}
15
+ s.require_paths = ["lib"]
16
+ s.rubygems_version = %q{1.3.1}
17
+ s.summary = %q{transformation of a subset of org-mode markup to html.}
18
+
19
+ if s.respond_to? :specification_version then
20
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
21
+ s.specification_version = 2
22
+
23
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
24
+ else
25
+ end
26
+ else
27
+ end
28
+ end
@@ -0,0 +1,92 @@
1
+ require 'lib/org'
2
+ require 'org/scope/org_mode'
3
+ require 'org/to/html'
4
+
5
+ module Org
6
+ class Token
7
+ include ToHtml
8
+ include ToToc
9
+
10
+ def html_a(*args)
11
+ link, desc = *values
12
+ href = link =~ /^https?:\/\// ? link : "/#{link}"
13
+ tag(:a, (desc || link), :href => href)
14
+ end
15
+ end
16
+ end
17
+
18
+ require 'bacon'
19
+ require 'hpricot'
20
+
21
+ Bacon.extend(Bacon::TestUnitOutput)
22
+ Bacon.summary_on_exit
23
+
24
+ describe Org::Markup do
25
+ def t(string) # short for transform
26
+ Org::OrgMode.apply(string).to_html
27
+ end
28
+
29
+ should 'markup headers' do
30
+ t("* header" ).should == '<h1 id="header">header</h1>'
31
+ t("** header" ).should == '<h2 id="header">header</h2>'
32
+ t("*** header" ).should == '<h3 id="header">header</h3>'
33
+ t("**** header" ).should == '<h4 id="header">header</h4>'
34
+ t("***** header" ).should == '<h5 id="header">header</h5>'
35
+ t("****** header").should == '<h6 id="header">header</h6>'
36
+ end
37
+
38
+ should 'markup inline' do
39
+ t('*foo*').should == '<p><b>foo</b></p>'
40
+ t('/foo/').should == '<p><i>foo</i></p>'
41
+ t('_foo_').should == '<p><u>foo</u></p>'
42
+ t('+foo+').should == '<p><s>foo</s></p>'
43
+ t('~foo~').should == '<p><blockquote>foo</blockquote></p>'
44
+ t('=foo=').should == '<p><code>foo</code></p>'
45
+ end
46
+
47
+ should 'markup table' do
48
+ table = Hpricot(t("|name|address|\n|manveru|home|\n|gojira|tokyo|\n")).at(:table)
49
+ (table/:tr).map{|tr| (tr/:td).map{|td| td.inner_text } }.
50
+ should == [%w[name address], %w[manveru home], %w[gojira tokyo]]
51
+ end
52
+
53
+ should 'markup link' do
54
+ t('[[home]]').should == '<p><a href="/home">home</a></p>'
55
+ t('[[home][Home]]').should == '<p><a href="/home">Home</a></p>'
56
+ t('[[http://go.to/]]').should == '<p><a href="http://go.to/">http://go.to/</a></p>'
57
+ t('[[http://go.to/][Go to]]').should == '<p><a href="http://go.to/">Go to</a></p>'
58
+ end
59
+
60
+ should 'work with \r, \n, and \n\r' do
61
+ t("a\nb").should == '<p>a<br />b</p>'
62
+ t("a\r\nb").should == t("a\nb")
63
+ t("a\rb").should == t("a\nb")
64
+ end
65
+
66
+ should 'markup unorderd lists' do
67
+ t(" * one").should == '<ul><li>one</li></ul>'
68
+ t(" * one\n * two").should == '<ul><li>one</li><li>two</li></ul>'
69
+ t(" * one
70
+ * two
71
+ * three").should == '<ul><li>one</li><li>two</li><li>three</li></ul>'
72
+ t(" + one").should == '<ul><li>one</li></ul>'
73
+ t(" - one").should == '<ul><li>one</li></ul>'
74
+ end
75
+
76
+ should 'markup ordered lists' do
77
+ t(" 1. one").should == '<ol><li>one</li></ol>'
78
+ t(" 1) one").should == '<ol><li>one</li></ol>'
79
+ t(" 1. one\n 2. two").should == '<ol><li>one</li><li>two</li></ol>'
80
+ end
81
+
82
+ should 'markup nested lists' do
83
+ t(" * one\n + nest1\n + nest2\n * two\n").should ==
84
+ '<ul><li>one</li><ul><li>nest1</li><li>nest2</li></ul></ul>'
85
+ t(" 1. one\n + nest1\n + nest2\n 2. two\n").should ==
86
+ '<ol><li>one</li><ul><li>nest1</li><li>nest2</li></ul></ol>'
87
+ end
88
+
89
+ should 'markup inline in lists' do
90
+ t(' * first _foo_ /bar/').should == '<ul><li>first <u>foo</u> <i>bar</i></li></ul>'
91
+ end
92
+ end
@@ -0,0 +1,49 @@
1
+ desc 'Run all bacon specs with pretty output'
2
+ task :bacon => :install_dependencies do
3
+ require 'open3'
4
+ require 'scanf'
5
+
6
+ specs = PROJECT_SPECS
7
+
8
+ some_failed = false
9
+ total = specs.size
10
+ len = specs.map{|s| s.size }.sort.last
11
+ tt = ta = tf = te = 0
12
+
13
+ red, yellow, green = "\e[31m%s\e[0m", "\e[33m%s\e[0m", "\e[32m%s\e[0m"
14
+ left_format = "%4d/%d: %-#{len + 11}s"
15
+ spec_format = "%d specifications (%d requirements), %d failures, %d errors"
16
+
17
+ specs.each_with_index do |spec, idx|
18
+ print(left_format % [idx + 1, total, spec])
19
+
20
+ Open3.popen3(RUBY, spec) do |sin, sout, serr|
21
+ out = sout.read
22
+ err = serr.read
23
+
24
+ ran = false
25
+
26
+ out.each_line do |line|
27
+ tests, assertions, failures, errors = all = line.scanf(spec_format)
28
+ next unless all.any?
29
+ ran = true
30
+ tt += tests; ta += assertions; tf += failures; te += errors
31
+
32
+ if tests == 0 || failures + errors > 0
33
+ puts((red % spec_format) % all)
34
+ puts out
35
+ puts err
36
+ else
37
+ puts((green % "%6d passed") % tests)
38
+ end
39
+
40
+ break
41
+ end
42
+
43
+ puts(yellow % " skipped") unless ran
44
+ end
45
+ end
46
+
47
+ puts(spec_format % [tt, ta, tf, te])
48
+ exit 1 if some_failed
49
+ end
@@ -0,0 +1,18 @@
1
+ desc 'update changelog'
2
+ task :changelog do
3
+ File.open('CHANGELOG', 'w+') do |changelog|
4
+ `git log -z --abbrev-commit`.split("\0").each do |commit|
5
+ next if commit =~ /^Merge: \d*/
6
+ ref, author, time, _, title, _, message = commit.split("\n", 7)
7
+ ref = ref[/commit ([0-9a-f]+)/, 1]
8
+ author = author[/Author: (.*)/, 1].strip
9
+ time = Time.parse(time[/Date: (.*)/, 1]).utc
10
+ title.strip!
11
+
12
+ changelog.puts "[#{ref} | #{time}] #{author}"
13
+ changelog.puts '', " * #{title}"
14
+ changelog.puts '', message.rstrip if message
15
+ changelog.puts
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ require 'rake/gempackagetask'
2
+
3
+ task :gemspec => [:manifest, :changelog] do
4
+ gemspec_file = "#{GEMSPEC.name}.gemspec"
5
+ File.open(gemspec_file, 'w+'){|gs| gs.puts(GEMSPEC.to_ruby) }
6
+ end
7
+
8
+ desc "package and install from gemspec"
9
+ task :install => [:gemspec] do
10
+ sh "gem build #{GEMSPEC.name}.gemspec"
11
+ sh "gem install #{GEMSPEC.name}-#{GEMSPEC.version}.gem"
12
+ end
13
+
14
+ desc "uninstall the gem"
15
+ task :uninstall => [:clean] do
16
+ sh %{gem uninstall -x #{GEMSPEC.name}}
17
+ end
18
+
19
+ Rake::GemPackageTask.new(GEMSPEC) do |p|
20
+ p.need_tar = true
21
+ p.need_zip = true
22
+ end
@@ -0,0 +1,76 @@
1
+ task :gem_installer do
2
+ class GemInstaller
3
+ def initialize(options = {}, &block)
4
+ @gems = []
5
+ @options = options
6
+
7
+ run(&block)
8
+ end
9
+
10
+ def run(&block)
11
+ instance_eval(&block) if block_given?
12
+ end
13
+
14
+ def gem(name, version = nil, options = {})
15
+ if version.respond_to?(:merge!)
16
+ options = version
17
+ else
18
+ options[:version] = version
19
+ end
20
+
21
+ @gems << [name, options]
22
+ end
23
+
24
+ def setup_gemspec(gemspec)
25
+ gemspec.dependencies.each do |dependency|
26
+ dependency.version_requirements.as_list.each do |version|
27
+ gem(dependency.name, version)
28
+ end
29
+ end
30
+
31
+ setup
32
+ end
33
+
34
+ def setup
35
+ require 'rubygems'
36
+ require 'rubygems/dependency_installer'
37
+
38
+ @gems.each do |name, options|
39
+ setup_gem(name, options)
40
+ end
41
+ end
42
+
43
+ def setup_gem(name, options, try_install = true)
44
+ print "activating #{name} ... "
45
+ Gem.activate(name, *[options[:version]].compact)
46
+ require(options[:lib] || name)
47
+ puts "success."
48
+ rescue LoadError => error
49
+ puts error
50
+ install_gem(name, options) if try_install
51
+ setup_gem(name, options, try_install = false)
52
+ end
53
+
54
+ def install_gem(name, options)
55
+ installer = Gem::DependencyInstaller.new(options)
56
+
57
+ temp_argv(options[:extconf]) do
58
+ print "Installing #{name} ... "
59
+ installer.install(name, options[:version])
60
+ puts "done."
61
+ end
62
+ end
63
+
64
+ def temp_argv(extconf)
65
+ if extconf ||= @options[:extconf]
66
+ old_argv = ARGV.clone
67
+ ARGV.replace(extconf.split(' '))
68
+ end
69
+
70
+ yield
71
+
72
+ ensure
73
+ ARGV.replace(old_argv) if extconf
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,12 @@
1
+ begin
2
+ require 'grancher/task'
3
+
4
+ Grancher::Task.new do |g|
5
+ g.branch = 'gh-pages'
6
+ g.push_to = 'origin'
7
+ g.message = 'Updated website'
8
+ g.directory 'ydoc', 'doc'
9
+ end
10
+ rescue LoadError
11
+ # oh well :)
12
+ end
@@ -0,0 +1,6 @@
1
+ desc 'install dependencies'
2
+ task :install_dependencies => [:gem_installer] do
3
+ GemInstaller.new do
4
+ setup_gemspec(GEMSPEC)
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ desc 'update manifest'
2
+ task :manifest do
3
+ File.open('MANIFEST', 'w+'){|io| io.puts(*GEMSPEC.files) }
4
+ end
@@ -0,0 +1,19 @@
1
+ desc 'code coverage'
2
+ task :rcov => :clean do
3
+ specs = Dir['spec/innate/**/*.rb']
4
+ specs -= Dir['spec/innate/cache/common.rb']
5
+
6
+ # we ignore adapter as this has extensive specs in rack already.
7
+ ignore = %w[ gem rack bacon innate/adapter\.rb ]
8
+ ignore << 'fiber\.rb' if RUBY_VERSION < '1.9'
9
+
10
+ ignored = ignore.join(',')
11
+
12
+ cmd = "rcov --aggregate coverage.data --sort coverage -t --%s -x '#{ignored}' %s"
13
+
14
+ while spec = specs.shift
15
+ puts '', "Gather coverage for #{spec} ..."
16
+ html = specs.empty? ? 'html' : 'no-html'
17
+ sh(cmd % [html, spec])
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ desc 'publish to github'
2
+ task :release => [:reversion, :gemspec] do
3
+ name, version = GEMSPEC.name, GEMSPEC.version
4
+
5
+ sh("git add MANIFEST CHANGELOG #{name}.gemspec lib/#{name}/version.rb")
6
+
7
+ puts "I added the relevant files, you can now run:", ''
8
+ puts "git commit -m 'Version #{version}'"
9
+ puts "git tag -a -m '#{version}' '#{version}'"
10
+ puts "git push"
11
+ puts
12
+ end
@@ -0,0 +1,8 @@
1
+ desc "update version.rb"
2
+ task :reversion do
3
+ File.open("lib/#{GEMSPEC.name}/version.rb", 'w+') do |file|
4
+ file.puts("module #{PROJECT_MODULE}")
5
+ file.puts(' VERSION = %p' % GEMSPEC.version.to_s)
6
+ file.puts('end')
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: org
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 2009
7
+ - 3
8
+ - 28
9
+ version: 2009.03.28
10
+ platform: ruby
11
+ authors:
12
+ - Michael 'manveru' Fellinger
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2009-03-28 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: transformation of a subset of org-mode markup to html.
22
+ email: m.fellinger@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - CHANGELOG
31
+ - MANIFEST
32
+ - README.md
33
+ - Rakefile
34
+ - doc/syntax.org
35
+ - lib/org.rb
36
+ - lib/org/markup.rb
37
+ - lib/org/rule.rb
38
+ - lib/org/rules.rb
39
+ - lib/org/scope.rb
40
+ - lib/org/scope/org_mode.rb
41
+ - lib/org/state.rb
42
+ - lib/org/stringscanner.rb
43
+ - lib/org/to/html.rb
44
+ - lib/org/to/toc.rb
45
+ - lib/org/token.rb
46
+ - lib/org/version.rb
47
+ - org.gemspec
48
+ - spec/org.rb
49
+ - tasks/bacon.rake
50
+ - tasks/changelog.rake
51
+ - tasks/gem.rake
52
+ - tasks/gem_installer.rake
53
+ - tasks/grancher.rake
54
+ - tasks/install_dependencies.rake
55
+ - tasks/manifest.rake
56
+ - tasks/rcov.rake
57
+ - tasks/release.rake
58
+ - tasks/reversion.rake
59
+ has_rdoc: true
60
+ homepage: http://github.com/manveru/org
61
+ licenses: []
62
+
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.7
88
+ signing_key:
89
+ specification_version: 2
90
+ summary: transformation of a subset of org-mode markup to html.
91
+ test_files: []
92
+