+ <%= link_to_if_authorized(
+ l(:button_raw),
+ {:action => 'raw', :id => @page_name},
+ :class => 'icon icon-file')
+ %>
+
<%= label(:gollum_wiki, :markup_language) %>
<%= select(:page, :format, options_for_select(Gollum::Page::FORMAT_NAMES.keys, @page_format), {:disabled => false}) %>
+ <% end %>
+
+<% if @project.gollum_wiki.store_as_wiki %>
+ <%= f.text_area :formatted_data, :class => "wiki-edit", :id=> 'raw_data_id', :cols => 100, :rows => 30 %>
+<% else %>
+ <%= f.text_area :raw_data, :class => "wiki-edit", :id=> 'raw_data_id', :cols => 100, :rows => 30 %>
+<% end %>
+
+<% if @project.gollum_wiki.use_ckeditor %>
+ <% if Redmine::Plugin.installed?('redmine_ckeditor') %>
+ <% if @project.gollum_wiki.use_ckeditor %>
+ <%= gollum_include_ckeditor 'raw_data_id' %>
+ <% end %>
+ <% else %>
+
<%= f.submit(l(:button_save)) %>
<% #preview
@@ -15,5 +44,16 @@
<%= link_to(l(:label_preview), previewScript) %>
<% end %>
+
+
+<% if @project.gollum_wiki.store_as_wiki %>
+ <%= link_to_if_authorized(
+ l(:button_raw),
+ {:action => 'raw', :id => @page_name},
+ :class => 'icon icon-file')
+ %>
+<% end %>
<% if @editable %>
<%= link_to_if_authorized(
l(:button_edit),
diff --git a/app/views/gollum_pages/upload.html.erb b/app/views/gollum_pages/upload.html.erb
new file mode 100644
index 0000000..76cbbf5
--- /dev/null
+++ b/app/views/gollum_pages/upload.html.erb
@@ -0,0 +1,9 @@
+
Upload file
+
Upload:
+
+<%= form_tag({:action => :upload}, :multipart => true) do %>
+ <%= file_field_tag "upload" %>
+
+<% end %>
+
+
diff --git a/app/views/gollum_wikis/_edit.html.erb b/app/views/gollum_wikis/_edit.html.erb
index d4de8ba..f394392 100644
--- a/app/views/gollum_wikis/_edit.html.erb
+++ b/app/views/gollum_wikis/_edit.html.erb
@@ -3,7 +3,7 @@
<%= label(:gollum_wiki, :git_path) %>
- <%= f.text_field :git_path %>
+ <%= f.text_field :git_path, :size => 50 %>
<%= label(:gollum_wiki, :markup_language) %>
@@ -13,6 +13,21 @@
<%= label(:gollum_wiki, :page_files_directory) %>
<%= f.text_field :directory %>
+
+ <%= label(:gollum_images_directory, :images_directory) %>
+ <%= f.text_field :images_directory %>
+
+
+ <% if @gollum_wiki.use_ckeditor && ! Redmine::Plugin.installed?('redmine_ckeditor') %>
+ Alert: redmine_ckeditor plugin is not installed
+ <% end %>
+ <%= label(:gollum_use_ckeditor, :use_ckeditor) %>
+ <%= f.check_box :use_ckeditor %>
+
+
+ <%= label(:gollum_edit_html_store_as_wiki, :edit_html_store_as_wiki) %>
+ <%= f.check_box :store_as_wiki %>
+
<%= f.submit %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 65f7ab7..b66811d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -5,4 +5,12 @@ en:
field_git_path: 'Git repository path'
field_markup_language: 'Markup language'
field_page_files_directory: 'Wiki pages directory'
+ button_raw: 'Raw'
+ label_raw: 'Raw'
+ upload: 'Upload'
+ new_page: 'New Page'
+ new_page_name: 'New page name'
+ create_new_page: 'Create new page'
+ list_pages: 'List Pages'
+
diff --git a/config/routes.rb b/config/routes.rb
index 6f98a14..202fe62 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,12 @@
resources :projects do
+ match 'img/:id.:ext' => 'gollum_pages#file'
+ match 'gollum_pages/img/:id.:ext' => 'gollum_pages#file'
+ match 'list' => 'gollum_pages#list'
+
+ get 'newpage' => 'gollum_pages#newpage'
+ post 'newpage' => 'gollum_pages#edit'
+ match 'upload' => 'gollum_pages#upload', :as => :upload
+ get 'gollum_pages/:id/raw' => 'gollum_pages#raw', :as => :raw
resources :gollum_pages do
collection do
post 'preview'
diff --git a/db/migrate/004_ckeditor_to_gollum_wikis.rb b/db/migrate/004_ckeditor_to_gollum_wikis.rb
new file mode 100644
index 0000000..4384534
--- /dev/null
+++ b/db/migrate/004_ckeditor_to_gollum_wikis.rb
@@ -0,0 +1,13 @@
+class CkeditorToGollumWikis < ActiveRecord::Migration
+ def self.up
+ add_column :gollum_wikis, :use_ckeditor, :boolean, :default => 0
+ add_column :gollum_wikis, :store_as_wiki, :boolean, :default => 0
+ add_column :gollum_wikis, :images_directory, :string, :default => 'img'
+ end
+
+ def self.down
+ remove_column :gollum_wikis, :use_ckeditor
+ remove_column :gollum_wikis, :store_as_wiki
+ remove_column :gollum_wikis, :images_directory
+ end
+end
diff --git a/init.rb b/init.rb
index 7d045e8..fefd9aa 100644
--- a/init.rb
+++ b/init.rb
@@ -38,8 +38,8 @@
:partial => 'shared/settings'
project_module :gollum_pages do
- permission :view_gollum_pages, :gollum_pages => [:index, :show]
- permission :add_gollum_pages, :gollum_pages => [:new, :create]
+ permission :view_gollum_pages, :gollum_pages => [:index, :show, :file, :raw, :list]
+ permission :add_gollum_pages, :gollum_pages => [:new, :create, :upload, :newpage]
permission :edit_gollum_pages, :gollum_pages => [:edit, :update]
permission :delete_gollum_pages, :gollum_pages => [:destroy]
diff --git a/lib/reverse_markdown.rb b/lib/reverse_markdown.rb
new file mode 100644
index 0000000..877ac7d
--- /dev/null
+++ b/lib/reverse_markdown.rb
@@ -0,0 +1,23 @@
+require 'reverse_markdown/version'
+require 'reverse_markdown/mapper'
+require 'reverse_markdown/errors'
+require 'nokogiri'
+
+module ReverseMarkdown
+
+ def self.parse(input, opts={})
+ root = case input
+ when String then Nokogiri::HTML(input).root
+ when Nokogiri::XML::Document then input.root
+ when Nokogiri::XML::Node then input
+ end
+
+ ReverseMarkdown::Mapper.new(opts).process_root(root)
+ end
+
+ # 2012/08/11 joe: possibly deprecate in favour of #parse
+ class << self
+ alias parse_string parse
+ alias parse_element parse
+ end
+end
diff --git a/lib/reverse_markdown/errors.rb b/lib/reverse_markdown/errors.rb
new file mode 100644
index 0000000..411ceea
--- /dev/null
+++ b/lib/reverse_markdown/errors.rb
@@ -0,0 +1,3 @@
+module ReverseMarkdown
+ class ParserError < StandardError; end
+end
\ No newline at end of file
diff --git a/lib/reverse_markdown/mapper.rb b/lib/reverse_markdown/mapper.rb
new file mode 100644
index 0000000..a2d87f0
--- /dev/null
+++ b/lib/reverse_markdown/mapper.rb
@@ -0,0 +1,248 @@
+module ReverseMarkdown
+ class Mapper
+ attr_accessor :raise_errors
+ attr_accessor :log_enabled, :log_level
+ attr_accessor :li_counter
+ attr_accessor :github_style_code_blocks
+
+ def initialize(opts={})
+ self.log_level = :info
+ self.log_enabled = true
+ self.li_counter = 0
+ self.github_style_code_blocks = opts[:github_style_code_blocks] || false
+ end
+
+ def process_root(element)
+ return '' if element.nil?
+
+ markdown = process_element(element) # recursively process all elements to get full markdown
+
+ # Extract github style code blocks
+ extractions = {}
+ markdown.gsub!(%r{```.*?```}m) do |match|
+ md5 = Digest::MD5.hexdigest(match)
+ extractions[md5] = match
+ "{code-block-extraction-#{md5}}"
+ end
+
+ markdown = markdown.split("\n").map do |line|
+ if line.match(/^( {4}|\t)/)
+ line
+ else
+ "#{ ' ' if line.match(/^ {2,3}/) }" +
+ normalize_whitespace(line).strip +
+ "#{ ' ' if line.match(/ {2}$/) }"
+ end
+ end.join("\n")
+
+ markdown.gsub!(/\n{3,}/, "\n\n")
+
+ # Insert pre block extractions
+ markdown.gsub!(/\{code-block-extraction-([0-9a-f]{32})\}/){ extractions[$1] }
+
+ markdown
+ end
+
+ def process_element(element)
+ output = ''
+ if element.text?
+ text = process_text(element)
+ if output.end_with?(' ') && text.start_with?(' ')
+ output << text.lstrip
+ else
+ output << text
+ end
+ else
+ output << opening(element).to_s
+
+ markdown_chunks = element.children.map { |child| process_element(child) }
+ remove_adjacent_whitespace!(markdown_chunks)
+ output << markdown_chunks.join
+
+ output << ending(element).to_s
+ end
+ output
+ end
+
+ private
+
+ # removes whitespace-only chunk if the previous chunk ends with whitespace
+ def remove_adjacent_whitespace!(chunks)
+ (chunks.size - 1).downto(1).each do |i|
+ chunk = chunks[i]
+ previous_chunk = chunks[i-1]
+ chunks.delete_at(i) if chunk == ' ' && previous_chunk.end_with?(' ')
+ end
+ end
+
+ def opening(element)
+ parent = element.parent ? element.parent.name.to_sym : nil
+ case element.name.to_sym
+ when :html, :body
+ ""
+ when :table
+ "\n"
+ when :tr
+ ""
+ when :td
+ "|"
+ when :th
+ "|="
+ when :li
+# indent = ' ' * [(element.ancestors('ol').count + element.ancestors('ul').count - 1), 0].max
+# if parent == :ol
+# "#{indent}#{self.li_counter += 1}. "
+# li_counter
+# else
+# "#{indent}- "
+# end
+ level = element.ancestors('ol').count + element.ancestors('ul').count
+ star = '*'
+ star = '#' if parent == :ol
+ ret = (star * level) + " "
+ ret
+ when :pre
+ "\n{{{\n"
+ when :ol
+ self.li_counter = 0
+ "\n"
+ when :ul, :root#, :p
+ "\n"
+ when :div
+ "\n"
+ when :p
+ if element.ancestors.map(&:name).include?('blockquote')
+ "\n\n> "
+ elsif [nil, :body].include? parent
+ is_first = true
+ previous = element.previous
+ while is_first == true and previous do
+ is_first = false unless previous.content.strip == "" || previous.text?
+ previous = previous.previous
+ end
+ is_first ? "" : "\n\n"
+ else
+ "\n\n"
+ end
+ when :h1, :h2, :h3, :h4 # /h(\d)/ for 1.9
+ element.name =~ /h(\d)/
+ "\n" + ('=' * $1.to_i) + ' '
+ when :em, :i
+ element.text.strip.empty? ? '' : '//' if (element.ancestors('em') + element.ancestors('i')).empty?
+ when :strong, :b
+ element.text.strip.empty? ? '' : '**' if (element.ancestors('strong') + element.ancestors('b')).empty?
+ when :blockquote
+ "> "
+ when :code
+ if parent == :pre
+ self.github_style_code_blocks ? "\n```\n" : "\n "
+ else
+ " `"
+ end
+ when :a
+ if !element.text.strip.empty? && element['href']
+ " ["
+ " [[#{element['href']}|"
+ else
+ " "
+ end
+ when :img
+ " !["
+ " "
+ when :hr
+ "\n----\n"
+ when :br
+ " \n"
+ else
+ handle_error "unknown start tag: #{element.name.to_s}"
+ ""
+ end
+ end
+
+ def ending(element)
+ parent = element.parent ? element.parent.name.to_sym : nil
+ case element.name.to_sym
+ when :html, :body, :hr
+ ""
+ when :pre
+ "\n}}}\n"
+ when :table
+ ""
+ when :tr
+ "|\n"
+ when :td
+ ""
+ when :th
+ ""
+ when :p
+ "\n\n"
+ when :div
+ "\n"
+ when :h1, :h2, :h3, :h4 # /h(\d)/ for 1.9
+ "\n"
+ when :em, :i
+ element.text.strip.empty? ? '' : '_' if (element.ancestors('em') + element.ancestors('i')).empty?
+ when :strong, :b
+ element.text.strip.empty? ? '' : '**' if (element.ancestors('strong') + element.ancestors('b')).empty?
+ when :li, :blockquote, :root, :ol, :ul
+ "\n"
+ when :code
+ if parent == :pre
+ self.github_style_code_blocks ? "\n```" : "\n"
+ else
+ '` '
+ end
+ when :a
+ "]]"
+# if !element.text.strip.empty? && element['href'] && !element['href'].start_with?('#')
+# "](#{element['href']}#{title_markdown(element)})"
+# else
+# ""
+# end
+ when :img
+ "#{element['alt']}](#{element['src']}#{title_markdown(element)}) "
+ "{{#{element['src']}|#{title_markdown(element)}}} "
+ else
+ handle_error "unknown end tag: #{element.name}"
+ ""
+ end
+ end
+
+ def title_markdown(element)
+ title = element['title']
+ title ? %[ "#{title}"] : ''
+ end
+
+ def process_text(element)
+ parent = element.parent ? element.parent.name.to_sym : nil
+ case
+ when parent == :code
+ if self.github_style_code_blocks
+ element.text
+ else
+ element.text.strip.gsub(/\n/,"\n ")
+ end
+ else
+ normalize_whitespace(escape_text(element.text))
+ end
+ end
+
+ def normalize_whitespace(text)
+ text.tr("\n\t", ' ').squeeze(' ')
+ end
+
+ def escape_text(text)
+ text.
+ gsub('*', '\*').
+ gsub('_', '\_')
+ end
+
+ def handle_error(message)
+ if raise_errors
+ raise ReverseMarkdown::ParserError, message
+ elsif log_enabled && defined?(Rails)
+ Rails.logger.__send__(log_level, message)
+ end
+ end
+ end
+end
diff --git a/lib/reverse_markdown/version.rb b/lib/reverse_markdown/version.rb
new file mode 100644
index 0000000..c56eea0
--- /dev/null
+++ b/lib/reverse_markdown/version.rb
@@ -0,0 +1,3 @@
+module ReverseMarkdown
+ VERSION = "0.4.3"
+end