# -*- coding: utf-8; -*-
#
# Wiki_style.rb: Wiki style for tDiary 2.x format. $Revision: 1.32 $
#
# if you want to use this style, add @style into tdiary.conf below:
#
#    @style = 'Wiki'
#
# Copyright (C) 2003, TADA Tadashi <t@tdtds.jp>
# Copyright (C) 2005, Kazuhiko <kazuhiko@fdiary.net>
# You can distribute this under GPL.
#
require 'hikidoc'

module TDiary
	class WikiSection
		include SectionBase

		def initialize( fragment, author = nil )
			@author = author
			if fragment[0] == ?! then
				@subtitle, @body = fragment.split( /\n/, 2 )
				@subtitle.sub!( /^\!\s*/, '' )
			else
				@subtitle = nil
				@body = fragment.dup
			end
			@body = @body || ''
			@body.sub!( /[\n\r]+\Z/, '' )
			@body << "\n\n"
			@categories = get_categories
			@stripped_subtitle = strip_subtitle

			@subtitle_to_html = @subtitle ? to_html( "!#{@subtitle}" ) : ''
			@body_to_html = to_html( @body )
			@html = @subtitle_to_html + "\n" +  @body_to_html + "\n"
			@subtitle_to_html = strip_headings( @subtitle_to_html )
			@body_to_html = strip_headings( @body_to_html )
			@stripped_subtitle_to_html = @stripped_subtitle ? strip_headings( to_html( "!#{@stripped_subtitle}" ) ) : nil
		end

		def subtitle=(subtitle)
			@subtitle = subtitle ? (categories_to_string + subtitle) : nil
			@stripped_subtitle = strip_subtitle
		end

		def categories=(categories)
			@subtitle = @subtitle ? (categories_to_string + @stripped_subtitle) : nil
			@stripped_subtitle = strip_subtitle
		end

		def to_src
			r = ''
			r << "! #{@subtitle}\n" if @subtitle
			r << @body
		end

		def do_html4( date, idx, opt )
			subtitle = false
			r = @html.lstrip
			r.sub!( %r!<h3>(.+?)</h3>!m ) do
				subtitle = true
				"<h3><%= subtitle_proc( Time.at( #{date.to_i} ), #{$1.dump.gsub( /%/, '\\\\045' )} ) %></h3>"
			end
			r.sub!( %r!^<p>(.+?)</p>$!m ) do
				"<p><%= subtitle_proc( Time.at( #{date.to_i} ), #{$1.dump.gsub( /%/, '\\\\045' )} ) %></p>"
			end unless subtitle
			r.gsub( /<(\/)?tdiary-section>/, '<\\1p>' )
		end

	private

		def valid_plugin_syntax?(code)
			lambda {
				$SAFE = 4
				eval( "BEGIN {return true}\n#{code}", nil, "(plugin)", 0 )
			}.call
		rescue SyntaxError
			lambda { eval('') }.call
			false
		end

		def to_html( string )
			html = HikiDoc::to_html( string,
				:level => 3,
				:empty_element_suffix => '>',
				:use_wiki_name => false,
				:allow_bracket_inline_image => false,
				:plugin_syntax => method(:valid_plugin_syntax?) ).strip
			html.gsub!( %r!<span class="plugin">\{\{(.+?)\}\}</span>!m ) do
				"<%=#{CGI.unescapeHTML($1)}\n%>"
			end
			html.gsub!( %r!<div class="plugin">\{\{(.+?)\}\}</div>!m ) do
				"<p><%=#{CGI.unescapeHTML($1)}\n%></p>"
			end
			html.gsub!( %r!<a href="(.+?)">(.+?)</a>! ) do
				k, u = $2, $1
				if /^(\d{4}|\d{6}|\d{8}|\d{8}-\d+)[^\d]*?#?([pct]\d+)?$/ =~ u then
					%Q[<%=my '#{$1}#{$2}', '#{escape_quote k}' %>]
				elsif /:/ =~ u
					scheme, path = u.split( /:/, 2 )
					if /\A(?:http|https|ftp|mailto)\z/ =~ scheme
      				u.sub!( /^\w+:/, '' ) if %r|://| !~ u and /^mailto:/ !~ u
						%Q[<a href="#{u}">#{k}</a>]
					elsif ( k == u )
						%Q[<%=kw '#{escape_quote u}'%>]
					else
						%Q[<%=kw '#{escape_quote u}', '#{escape_quote k}'%>]
					end
				elsif k == u
					%Q[<%=kw '#{escape_quote u}', '#{escape_quote k}'%>]
				else
					%Q[<a href="#{u}">#{k}</a>]
				end
			end
			html
		end

		def escape_quote( s )
			s.gsub( /'/, "\\\\'" )
		end

		def strip_headings( string )
			html = string
			html.sub!( /\A<h3>/, '' )
			html.sub!( %r|</h3>\z|, '' )
			html.empty? ? nil : html
		end

		def get_categories
			return [] unless @subtitle
			cat = /^(\[([^\[]+?)\])+/.match(@subtitle).to_a[0]
			return [] unless cat
			cat.scan(/\[(.*?)\]/).collect do |c|
				c[0].split(/,/)
			end.flatten
		end

		def strip_subtitle
			return nil unless @subtitle
			r = @subtitle.sub(/^(\[[^\[]+?\])+\s*/,'')
			if r == ""
				nil
			else
				r
			end
		end
	end

	class WikiDiary
		include DiaryBase
		include CategorizableDiary

		def initialize( date, title, body, modified = Time.now )
			init_diary
			replace( date, title, body )
			@last_modified = modified
		end

		def style
			'Wiki'
		end

		def append( body, author = nil )
			# body1 is a section starts without subtitle.
			# body2 are sections starts with subtitle.
			if /(.*?)(^![^!].*)/m =~ body
				body1 = $1
				body2 = $2
			elsif /^![^!]/ !~ body
				body1 = body
				body2 = ''
			else
				body1 = ''
				body2 = body
			end

			unless body1.empty?
				current_section = @sections.pop
				if current_section then
					body1 = "#{current_section.to_src.sub( /\n+\Z/, '' )}\n\n#{body1}"
				end
				@sections << WikiSection::new( body1, author )
			end
			section = nil
			body2.each_line do |l|
				case l
				when /^\![^!]/
					@sections << WikiSection::new( section, author ) if section
					section = l
				else
					section = '' unless section
					section << l
				end
			end
			@sections << WikiSection::new( section, author ) if section
			@last_modified = Time.now
			self
		end

		def add_section(subtitle, body)
			@sections << WikiSection::new("! #{subtitle}\n#{body}")
			@sections.size
		end
	end
end

# Local Variables:
# mode: ruby
# indent-tabs-mode: t
# tab-width: 3
# ruby-indent-level: 3
# End:
