Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Got FFI::Upskirt::Document rendering Markdown as HTML.
  • Loading branch information
postmodern committed May 12, 2011
1 parent a11c0bd commit 9ed5fd6
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 4 deletions.
87 changes: 83 additions & 4 deletions lib/ffi/upskirt/buffer.rb
Expand Up @@ -10,13 +10,92 @@ class Buffer < FFI::Struct
:unit, :size_t, :unit, :size_t,
:ref, :int :ref, :int


#
# Creates a new empty buffer.
#
# @param [Integer] size
# The size of the new buffer.
#
# @yield [buffer]
# The given block will be passed the new buffer.
#
# @yieldparam [Buffer] buffer
# The new buffer.
#
# @return []
# Once the block has returned, the buffer will be released.
#
def self.create_empty(size)
buffer = new(Upskirt.bufnew(size))

yield buffer

Upskirt.bufrelease(buffer)
end

#
# Creates a new buffer.
#
# @param [String] text
# The text to populate the buffer with.
#
# @yield [buffer]
# The given block will be passed the new buffer.
#
# @yieldparam [Buffer] buffer
# The new buffer.
#
# @return []
# Once the block has returned, the buffer will be deallocated.
#
def self.create_from(text)
data = FFI::MemoryPointer.new(:char,text.length + 1)
data.put_string(0,text)

buffer = new()
buffer[:size] = text.length
buffer[:data] = data

yield buffer

data.free
end

#
# Increases the size of the buffer.
#
# @param [Integer] length
# The length to increase the buffer by.
#
def grow(length)
Upskirt.bufgrow(self,length)
end

#
# The contents of the buffer.
#
# @return [String]
# The data within the buffer.
#
def to_s
self[:data].get_string(0,self[:size])
end

#
# Applies smartypants rendering to the buffer.
#
# @return [String]
# The smartypants rendered contents of the buffer.
#
def to_smartypants def to_smartypants
smart_buffer = Upskirt.bufnew(128) result = nil

Buffer.create_empty(128) do |smart_buffer|
Upskirt.upshtml_smartypants(smart_buffer,self)


Upskirt.upshtml_smartypants(smart_buffer,self) result = self.to_s
result = smart_buffer.data.get_string(0,smart_buffer.size) end


smart_buffer.free
return result return result
end end


Expand Down
162 changes: 162 additions & 0 deletions lib/ffi/upskirt/document.rb
@@ -1,12 +1,174 @@
require 'ffi/upskirt/types'
require 'ffi/upskirt/buffer'
require 'ffi/upskirt/renderer'

module FFI module FFI
module Upskirt module Upskirt
class Document class Document


# The `render_mode` enum
RENDER_MODES = Upskirt.enum_type(:render_mode)

# The `markdown_extensions` enum
EXTENSIONS = Upskirt.enum_type(:markdown_extensions)

# Valid options for {#initialize}
VALID_OPTIONS = RENDER_MODES.symbols + EXTENSIONS.symbols

attr_accessor :no_intra_emphasis

attr_accessor :tables

attr_accessor :fenced_code

attr_accessor :autolink

attr_accessor :strikethrough

attr_accessor :lax_html_blocks

attr_accessor :space_headers

attr_accessor :skip_html

attr_accessor :skip_style

attr_accessor :skip_images

attr_accessor :skip_links

attr_accessor :expand_tabs

attr_accessor :safelink

attr_accessor :toc

attr_accessor :hard_wrap

attr_accessor :github_blockcode

attr_accessor :use_xhtml

attr_accessor :smart

#
# Creates a new Document.
#
# @param [String] source
# The markdown source of the document.
#
# @param [Hash] options
# Additional options.
#
# @option options [Boolean] :smart
# Enables additional smartypants rendering.
#
def initialize(source='',options={}) def initialize(source='',options={})
@source = source @source = source
@smart = options.delete(:smart)

(VALID_OPTIONS & options.keys).each do |key|
instance_variable_set("@#{key}",options[key])
end
end end


#
# Converts the Markdown Document to HTML.
#
# @return [String]
# The rendered HTML.
#
def to_html def to_html
result = nil

Renderer.html(render_flags) do |renderer|
result = render(renderer)
end

return result
end

#
# Creates a Table of Contents (TOC) of the document.
#
# @return [String]
# The rendered Table of Contents.
#
def to_toc
result = nil

Renderer.toc do |renderer|
result = render(renderer)
end

return result
end

protected

#
# The enabled markdown extensions flags.
#
# @return [Integer]
# The combined flags as an unsigned integer.
#
def extensions
flags = 0

EXTENSIONS.symbols.each do |name|
if instance_variable_get("@#{name}")
flags |= EXTENSIONS[name]
end
end

return flags
end

#
# The enabled rendering flags.
#
# @return [Integer]
# The combined flags as an unsigned integer.
#
def render_flags
flags = 0

RENDER_MODES.symbols.each do |name|
if instance_variable_get("@#{name}")
flags |= RENDER_MODES[name]
end
end

return flags
end

#
# Renders the markdown source.
#
# @param [Renderer] renderer
# The renderer to use.
#
# @return [String]
# The rendered output.
#
def render(renderer)
result = nil

Buffer.create_from(@source) do |input_buffer|
Buffer.create_empty(128) do |output_buffer|
output_buffer.grow(@source.length * 1.2)

Upskirt.ups_markdown(output_buffer,input_buffer,renderer,extensions)

result = if @smart
output_buffer.to_smartypants
else
output_buffer.to_s
end
end
end

return result
end end


end end
Expand Down
50 changes: 50 additions & 0 deletions lib/ffi/upskirt/renderer.rb
@@ -1,3 +1,5 @@
require 'ffi/upskirt/upskirt'

module FFI module FFI
module Upskirt module Upskirt
class Renderer < FFI::Struct class Renderer < FFI::Struct
Expand Down Expand Up @@ -29,6 +31,54 @@ class Renderer < FFI::Struct
:doc_footerm, :doc_footer_callback, :doc_footerm, :doc_footer_callback,
:opaque, :pointer :opaque, :pointer


#
# Creates a new HTML renderer.
#
# @param [Integer] flags
# Render flags for the new renderer.
#
# @yield [renderer]
# The given block will be passed the new renderer.
#
# @yieldparam [Renderer] renderer
# The new renderer.
#
# @return []
# After the given block has returned, the renderer will be freed.
#
def Renderer.html(flags)
renderer = new
Upskirt.upshtml_renderer(renderer,flags)

yield renderer

Upskirt.upshtml_free_renderer(renderer)
end

#
# Creates a new Table of Contents (TOC) renderer.
#
# @param [Integer] flags
# Render flags for the new renderer.
#
# @yield [renderer]
# The given block will be passed the new renderer.
#
# @yieldparam [Renderer] renderer
# The new renderer.
#
# @return []
# After the given block has returned, the renderer will be freed.
#
def Renderer.toc
renderer = new
Upskirt.upshtml_toc_renderer(renderer)

yield renderer

Upskirt.upshtml_free_renderer(renderer)
end

end end
end end
end end

0 comments on commit 9ed5fd6

Please sign in to comment.